1个简单表单,4种编码风格(react、vue2、vue3写法对比)
发布于 2022年 01月 23日 21:08
Vue3版本发布了,不仅更改了底层对数据响应的实现方式,还推出了全新的组合式API (Composition API),带来了一种不一样的开发体验。
虽然有些人说组合式API是抄袭了React的Hooks。但在开源的世界中,没有什么所谓的抄不抄袭。只有谁更好用,能够解决更多的问题,开发体验更好。
从vue3的组合式api,再追溯到更早之前react的hooks,大家似乎都在朝着一个方向奔跑,这个方向或许将成为前端开发的一股新的浪潮,那这股浪潮是什么呢?它就是———函数式编程
。
在这里不发表过多对函数式编程的看法,只是作为一名小小的前端开发人员,在无力改变浪潮的前提下,只能顺势成为一个随波逐流的人儿。
一、简单的需求
本次的需求很简单,就是实现一个注册表单,用户输入用户名、手机号、密码、确认密码,点击注册打印出用户填入的信息即可。
下面就从使用不同的技术栈,来体验一下4种不同风格的编码吧。
二、使用vue2实现
// RegisterForm.vue
<template>
<form class="reg-form" @submit.prevent="handleRegister">
<div class="reg-form-item">
<div>用户名:</div>
<input
type="text"
:value="formData.userName"
@change="handleUserChange('userName', $event)"
placeholder="请输入用户名"
/>
</div>
<div class="reg-form-item">
<div>手机号:</div>
<input
type="text"
:value="formData.userPhone"
@change="handleUserChange('userPhone', $event)"
placeholder="请输入手机号"
/>
</div>
<div class="reg-form-item">
<div>密码:</div>
<input
type="password"
:value="formData.userPassword"
@change="handleUserChange('passwordAgain', $event)"
placeholder="请输入密码"
/>
</div>
<div class="reg-form-item">
<div>确认密码:</div>
<input
type="password"
:value="formData.passwordAgain"
@change="handleUserChange('userPassword', $event)"
placeholder="请输入确认密码"
/>
</div>
<div class="reg-btn">
<button>确认注册</button>
</div>
</form>
</template>
<script>
export default {
data() {
return {
formData: {
userName: "",
userPhone: "",
userPassword: "",
passwordAgain: "",
},
};
},
methods: {
// 处理注册事件
handleRegister() {
console.log(
`用户名:${this.formData.userName},手机号:${this.formData.userPhone},密码:${this.formData.userPassword}。`
);
},
// 处理用户数据收集
handleUserChange(type, e) {
if (type in this.formData) {
this.formData[type] = e.target.value;
}
},
},
};
</script>
<style scoped>
.reg-form {
width: 300px;
padding: 20px;
margin: 20px;
border: 1px solid #ddd;
}
.reg-form-item {
display: flex;
padding: 5px 0;
}
.reg-form-item > div {
width: 80px;
line-height: 30px;
text-align: right;
}
.reg-form-item > input {
padding: 5px;
width: 200px;
}
.reg-btn {
text-align: center;
margin-top: 20px;
}
.reg-btn button {
width: 90%;
}
</style>
技术总结:
1、vue2采用三段式
(template、script、style 标签)实现一个页面一个组件的开发体验。
2、使用v-bind
(:value) 绑定数据,v-on
绑定事件(@change)。
3、如果事件回调方法需要传参数,event会丢失,vue为我们提供了$event
参数来获取event。
4、prevent
是事件修饰符,可以阻止事件默认行为,等同event.preventDefault()
。
其实上例采用的是单向数据流的方式实现,vue其实是可以对表单作双向数据绑定,只需要使用v-model
。
<template>
<form class="reg-form" @submit.prevent="handleRegister">
<div class="reg-form-item">
<div>用户名:</div>
<input
type="text"
v-model="formData.userName"
placeholder="请输入用户名"
/>
</div>
<div class="reg-form-item">
<div>手机号:</div>
<input
type="text"
v-model="formData.userPhone"
placeholder="请输入手机号"
/>
</div>
<div class="reg-form-item">
<div>密码:</div>
<input
type="password"
v-model="formData.userPassword"
placeholder="请输入密码"
/>
</div>
<div class="reg-form-item">
<div>确认密码:</div>
<input
type="password"
v-model="formData.passwordAgain"
placeholder="请输入确认密码"
/>
</div>
<div class="reg-btn">
<button>确认注册</button>
</div>
</form>
</template>
<script>
export default {
data() {
return {
formData: {
userName: "",
userPhone: "",
userPassword: "",
passwordAgain: "",
},
};
},
methods: {
// 处理注册事件
handleRegister() {
console.log(
`用户名:${this.formData.userName},手机号:${this.formData.userPhone},密码:${this.formData.userPassword}。`
);
},
},
};
</script>
<style scoped>
// ... 省略
</style>
三、使用vue3实现
<script setup>
// 组合式api
import { reactive } from "vue";
const formData = reactive({
userName: "",
userPhone: "",
userPassword: "",
passwordAgain: "",
});
// 处理注册事件
const handleRegister = () => {
console.log(
`用户名:${formData.userName},手机号:${formData.userPhone},密码:${formData.userPassword}。`
);
};
</script>
<template>
<form class="reg-form" @submit.prevent="handleRegister">
<div class="reg-form-item">
<div>用户名:</div>
<input
type="text"
v-model="formData.userName"
placeholder="请输入用户名"
/>
</div>
<div class="reg-form-item">
<div>手机号:</div>
<input
type="text"
v-model="formData.userPhone"
placeholder="请输入手机号"
/>
</div>
<div class="reg-form-item">
<div>密码:</div>
<input
type="password"
v-model="formData.userPassword"
placeholder="请输入密码"
/>
</div>
<div class="reg-form-item">
<div>确认密码:</div>
<input
type="password"
v-model="formData.passwordAgain"
placeholder="请输入确认密码"
/>
</div>
<div class="reg-btn">
<button>确认注册</button>
</div>
</form>
</template>
<style scoped>
// ... 省略
</style>
技术总结:
1、vue3延续了vue2三段式开发风格,新增了<script setup>
标签,可以便捷的编写setup函数,并且不需要return就可以直接使用变量。
2、reactive
函数可以定义一个对象类型
的响应式数据。
注:关于vue3的知识点,可以参考《vue3开发使用体验,来一波技术性总结》
四、使用react类式组件实现
import React, { Component } from 'react'
export default class RegisterForm extends Component {
state = {
formData: {
userName: "",
userPhone: "",
userPassword: "",
passwordAgain: ""
}
}
// 处理注册事件
handleRegister = (e) => {
e.preventDefault();
const { formData: { userName, userPhone, userPassword } } = this.state;
console.log(
`用户名:${userName},手机号:${userPhone},密码:${userPassword}。`
);
}
// 处理用户数据收集
handleUserChange = (type) => {
return (e) => {
if (type in this.state.formData) {
this.setState(({ formData }) => ({
formData: {
...formData,
[type]: e.target.value
}
}))
}
}
}
render() {
const { formData: { userName, userPhone, userPassword, passwordAgain } } = this.state;
return (
<form className="reg-form" onSubmit={this.handleRegister} >
<div className="reg-form-item">
<div>用户名:</div>
<input
type="text"
value={userName}
onChange={this.handleUserChange('userName')}
placeholder="请输入用户名"
/>
</div>
<div className="reg-form-item">
<div>手机号:</div>
<input
type="text"
value={userPhone}
onChange={this.handleUserChange('userPhone')}
placeholder="请输入手机号"
/>
</div>
<div className="reg-form-item">
<div>密码:</div>
<input
type="password"
value={userPassword}
onChange={this.handleUserChange('userPassword')}
placeholder="请输入密码"
/>
</div>
<div className="reg-form-item">
<div>密码:</div>
<input
type="password"
value={passwordAgain}
onChange={this.handleUserChange('passwordAgain')}
placeholder="请输入确认密码"
/>
</div>
<div className="reg-btn">
<button>确认注册</button>
</div>
</form>
)
}
}
技术总结:
1、编写react类式组件需要继承React.Component
,HTML可以采用jsx
语法写在render
函数中进行渲染。
2、在表单项中使用state
进行管理则会成为受控组件
(value={userName})。
3、在react中处理事件的回调要特别注意this
的指向,一般回调函数会使用箭头函数,就是为了解决这一问题(handleRegister = (e) => { ... })。
4、不能直接改state的值(this.state.userName = 'new name'),需要使用this.setState()
函数进行处理。才能重新渲染新的dom。
5、react没有vue中的事件修饰符,需要自己处理原生事件冒泡
、事件默认行为
等(e.preventDefault())。
6、处理事件的回调函数如果想要传参数,event会丢失,采用高阶函数
、柯里化函数
可以解决这个问题。
handleUserChange = (type) => {
// 这种函数中返回函数的方式称为高阶函数
// fun(a)(b) 这种将接收多个参数变为接收单一参数,最终将参数统一处理并返回的编码方式称为柯里化函数。
return (e) => {
// ...
}
}
五、使用react函数式组件实现
import React, { useState } from 'react'
export default () => {
const [formData, setFormData] = useState({ // 使用useState Hooks
userName: '',
userPhone: '',
userPassword: '',
passwordAgain: ''
})
const { userName, userPhone, userPassword } = formData;
const handleRegister = (e) => {
e.preventDefault();
console.log(
`用户名:${userName},手机号:${userPhone},密码:${userPassword}。`
);
}
// 处理用户数据收集
const handleUserChange = (type) => {
return (e) => {
if (type in formData) {
setFormData({
...formData,
[type]: e.target.value
})
}
}
}
return (
<form className="reg-form" onSubmit={handleRegister} >
<div className="reg-form-item">
<div>用户名:</div>
<input
type="text"
value={userName}
onChange={handleUserChange('userName')}
placeholder="请输入用户名"
/>
</div>
<div className="reg-form-item">
<div>手机号:</div>
<input
type="text"
value={userPhone}
onChange={handleUserChange('userPhone')}
placeholder="请输入手机号"
/>
</div>
<div className="reg-form-item">
<div>密码:</div>
<input
type="password"
value={userPassword}
onChange={handleUserChange('userPassword')}
placeholder="请输入密码"
/>
</div>
<div className="reg-form-item">
<div>密码:</div>
<input
type="password"
value={passwordAgain}
onChange={this.handleUserChange('passwordAgain')}
placeholder="请输入确认密码"
/>
</div>
<div className="reg-btn">
<button>确认注册</button>
</div>
</form>
)
}
技术总结:
1、Hooks
可以让我们在函数组件中使用类式组件的状态、生命函数钩子等。
2、useState()
函数可以进行状态管理,除此之处还有useEffect()
(管理生命周期)、useRef()
(处理与DOM交互)等函数钩子。具体参照官网
六、总结
vue和react相关的知识体系是很庞大的,限于篇幅,就不展开讲了。只是想通过上述的简单例子,做一个抛砖引玉,让大家体验不同技术栈不同风格的开发方式。
至于vue和react孰优孰劣,我们没法简单的进行比较,毕竟它们所专注的点不同:
vue,许多API设计都是开箱即用的。我们只需要会用,就能快速轻松的实现功能。这跟框架的设计思想有关,vue是一种渐进式js框架,一步步从易到难,让你快速上手,传播的是一种易用的思想。
react,关注点在于构建易用的UI组件界面,提供一种更接近原生js的开发体验。这是一种优势,可以让组件的设计更加灵活,更加高效。
所以vue和react不是说哪个优哪个劣,对于前端生态来说,他俩都是优秀的框架和库。当然了,我们并不是在做选择题,二选一。做为一名合格的前端工程师来说,两者兼得才是最优解。