1个简单表单,4种编码风格(react、vue2、vue3写法对比)

1个简单表单,4种编码风格(react、vue2、vue3写法对比)

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>// 组合式apiimport { 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不是说哪个优哪个劣,对于前端生态来说,他俩都是优秀的框架和库。当然了,我们并不是在做选择题,二选一。做为一名合格的前端工程师来说,两者兼得才是最优解。

免责声明:本网信息来自于互联网,目的在于传递更多信息,并不代表本网赞同其观点。其原创性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容、文字的真实性、完整性、及时性本站不作任何保证或承诺,并请自行核实相关内容。本站不承担此类作品侵权行为的直接责任及连带责任。如若本网有任何内容侵犯您的权益,请及时联系我们,本站将会在24小时内处理完毕。
相关文章
返回顶部