适合Vue用户的React教程,你值得拥有(二)
发表时间:2021-1-5
发布人:葵宇科技
浏览次数:89
今天这篇文章将会对Vue2
,Vue3
,React
的一些用法进行对比,方便小伙伴们学习。
数据data
,在react
中叫state
熟悉vue
的小伙伴一定对Vue
中的data
不会感到陌生的,反正天天写Bug
的时候都要用,但是对于data
来说,在Vue2.0
,Vue3.0
,React
中用法是不同的,我们下面依次举例说明
Vue2.0
中的用法
如下代码是一个比较简单的Vue2.0
的data
用法
<template>
<div>{{ name }}div>
template>
<script>
export default {
data() {
return {
name: '子君',
gzh: '前端有的玩'
}
}
}
script>
复制代码
通过上面的代码我们可以看到data
是一个函数,然后函数中返回了一个对象,那么为什么data
是一个函数呢?比如我们有时候也会在App.vue
文件中看到data
不是函数的情况。
<template>
<div id="app">
<router-view />
div>
template>
<script>
export default {
data:{
name: '子君',
sex: '男'
}
}
script>
复制代码
那么为什么我们在普通组件里面还要将data
声明为函数呢?Vue
官网是这样解释的:当一个组件被定义,data
必须声明为返回一个初始数据对象的函数,因为组件可能被用来创建多个实例。如果 data
仍然是一个纯粹的对象,则所有的实例将共享引用同一个数据对象!通过提供 data
函数,每次创建一个新实例后,我们能够调用 data
函数,从而返回初始数据的一个全新副本数据对象。
而App.vue
可以将data
声明为一个普通对象是因为整个系统中App.vue
只会被使用到一次,所以不存在上述的问题。
Vue3
中的用法
在Vue3
中,我们依然可以像Vue2
那样去使用data
,当然Vue3
提供了新的Composition API
,在后续文章中,如果没有特殊说明,我们提到Vue3
就默认指的是使用Composition API
。
在Composition API
提供了响应式API
,分别是ref
和reactive
,通过这两个API
可以生成响应式的数据
基础用法
<template>
<div class="home">
<div>姓名:{{ state.name }}div>
<div>公众号:{{ state.gzh }}div>
<div>统计:{{ count }}div>
div>
template>
<script lang="ts">
import { defineComponent, reactive, ref } from "vue";
export default defineComponent({
name: "Home",
setup() {
const state = reactive({
name: "子君",
gzh: "前端有的玩"
});
const count = ref(0);
return {
state,
count
};
}
});
script>
复制代码
响应数据修改
在Vue2.0
中,我们修改data
的方式一般会使用this.name = '张三'
这种赋值的方式,但是对于Composition API
中因为提供了两种api
,所以用法稍有区别
<template>
<div class="home" @click="handleClick">
<div>姓名:{{ state.name }}div>
<div>公众号:{{ state.gzh }}div>
<div>统计:{{ count }}div>
div>
template>
<script lang="ts">
import { defineComponent, reactive, ref } from "vue";
export default defineComponent({
setup() {
const state = reactive({
name: "子君",
gzh: "前端有的玩"
});
const count = ref(0);
function handleClick() {
state.name = "张三";
count.value++;
}
return {
state,
count,
handleClick
};
}
});
script>
复制代码
如上代码所示:
-
对于
reactive
声明的数据对于
reactive
,我们可以通过state.name
来获取数据,然后通过state.name='张三'
来修改数据 -
对于
ref
声明的数据对于
ref
声明的数据,ref
接受一个参数值并返回一个响应式且可改变的 ref 对象。ref 对象拥有一个指向内部值的单一属性.value
。所以我们在代码中获取ref
对象的数据需要使用count.value
的方式,修改值的方式也需要通过count.value++
的方式。但是这里有一个特殊的点就是在
template
,ref
对象会自动解套,意思就是对于,代码里面可以直接使用统计:{{ count }}
count
,而不需要写成count.value
,Vue
自己就会将其解套为count.value
。
React
中的用法
React16.8
新增了Hook
特性,现在许多团队已经大规模使用了,所以本文的内容更多的是以Hook
为主。
在Vue3.0
中提供了Composition API
,其实这个和React
的hook
用法是很相似的,接下来我们将上文中我们写的Vue3.0
代码修改为React
版本
import React, { useState } from 'react'
export default function() {
// useState传入要初始化的状态数据,然后会返回一个数组
// 数组第一项为声明的数据,而第二个参数是一个方法,用于调用
// 修改数据
const [name, setName] = useState('子君')
const [gzh] = useState('前端有的玩')
function handleClick() {
// 在react修改数据需要调用useState返回的方法
setName('张三')
}
return (
<div onClick={handleClick}>
<div>姓名:{name}div>
<div>公众号: {gzh}div>
div>
);
}
复制代码
在这段代码中我们使用到了useState
声明了一个state
变量,useState
返回的值是一个数组,然后我们通过数组解构获取到了两个变量, const [name, setName] = useState('子君')
, 其中name
对应声明的state
变量,而setName
是一个函数,调用setName
可以修改变量的值,比如setName('张三')
,这时候name
的值就会变成了张三
侦听器watch
,监督你没毛病
小编在平常开发中是比较常用watch
的,使用watch
可以去监听数据的变化,然后在变化之后做一系列的操作。比如有一个列表页,我们希望用户在输入搜索关键字的时候,可以自动触发搜索。此时除了监听输入框的input
事件之外,还可以通过vue
的watch
来监听关键字的变化
Vue2.0
中的写法
在vue2.0
中,watch
常用的写法包含了两种,下面我们分别使用不同的写法来进行上述功能的实现
-
常规实现
<template> <div> <div> <span>搜索span> <input v-model="searchValue" /> div> div> template> <script> export default { data() { return { searchValue: '' } }, watch: { // 在值发生变化之后,重新加载数据 searchValue(newValue, oldValue) { // 判断搜索 if (newValue !== oldValue) { // 在这里处理搜索逻辑 } } } } script> 复制代码
-
使用
$watch
实现<template> <div> <div> <span>搜索span> <input v-model="searchValue" /> div> div> template> <script> export default { data() { return { searchValue: '' } }, created() { // $watch会返回一个unwatch函数,如果需求上需要在某些场景取消watch,可以执行`unwatch` const unwatch = this.$watch('searchValue', (newValue, oldValue) => { // 判断搜索 if (newValue !== oldValue) { // 在这里处理搜索逻辑 } }) } } script> 复制代码
在调用
$watch
的时候,会有一个返回值unwatch
,然后如果需要取消watch监听,我们可以通过调用unwatch
来进行,比如有一个表单,表单上面的保存按钮平常是置灰的,但是假如用户对表单进行了修改,就需要将表单的置灰状态修改为启用状态。但是如果表单已经启用了,就没必要继续watch
了,这时候就需要使用unwatch
Vue3.0
中的写法
在Vue3.0
中除了Vue2.0
中的写法外,还在Composition API
提供了watch
与watchEffect
两个API
,用于监听数据的变化,下面我们将上面搜索分别使用watch
与watchEffect
来实现
watch
实现方式
<template>
<div>
<span>搜索span>
<input v-model="state.searchValue" />
div>
template>
<script lang="ts">
import { defineComponent, reactive, watch } from "vue";
export default defineComponent({
setup() {
const state = reactive({
searchValue: ""
});
// 通过watch来监听searchValue的变化
const unwatch = watch(
() => state.searchValue,
(value, oldValue) => {
if (value !== oldValue) {
// 在这里处理搜索逻辑
}
}
);
return {
state
};
}
});
script>
复制代码
watch API
与Vue2.0
中的this.$watch
用法基本是一致的,包括使用的参数等,同时watch API
返回了unwatch
函数用于取消watch
同时watch
还可以侦听多个属性的变化,就像下面这样
watch([a,b,c], ([a,b,c],[oldA,oldB,oldC]) => {
})
复制代码
-
watchEffect
实现watchEffect
参数是一个函数,在代码执行时,会立即执行watchEffect
传入的函数,然后响应式追踪其依赖,并在其中某些依赖发生变化时重新运行该函数。我们将上述搜索代码使用watchEffect
来实现export default defineComponent({ setup() { const state = reactive({ searchValue: "" }); // 加载数据 function loadData(searchValue){ } // 通过watchEffect来监听searchValue的变化 const unwatch = watchEffect(() => { // 当代码执行到watchEffect时,会立即调用此函数,同时会收集到存在 //`state.searchValue`的依赖,然后当`state.searchValue`发生 //变化时会在此调用watchEffect,已实现数据监听 loadData(state.searchValue) }); return { state }; } }) 复制代码
React
中的用法
在React
中与watch
比较相似的功能是Effect Hook
,使用它可以让你在函数组件中执行副作用操作,先来看一下代码
import React, { useEffect, useState } from 'react'
export default function() {
// useState传入要初始化的状态数据,然后会返回一个数组
// 数组第一项为声明的数据,而第二个参数是一个方法,用于调用
// 修改数据
const [searchValue, setSearchValue] = useState('')
function handleChange(e: React.ChangeEvent ) {
// 在react修改数据需要调用useState返回的方法
setSearchValue(e.target.value);
}
// useEffect接受两个参数,第一个是回调函数,第二个是要监听变化的属性,是一个数组
useEffect(() => {
// 当代码首次调用useEffect会进入这个回调函数,然后
// 当serchValue 发生变化时,会再次进入到这里
console.log(111)
},[searchValue])
return (
<div>
<input value={searchValue} onChange={handleChange}>input>
div>
);
}
复制代码
如上代码我们使用useEffect
来监听searchValue
的变化,然后触发新的逻辑,但是看到上面代码,我们并没有发现取消effect
的方法,那么如何取消呢?
useEffect
第二个参数是一个数组,通过给数组传入要监听的变量来实现数据监听,但是却没有办法去取消这个监听,所以我们需要曲线救国,就像下面代码这样
const [isWatch] = useState(true)
useEffect(() => {
// 通过isWatch来判断是否进行监听逻辑变化
if(isWatch) {
// 监听数据变化
console.log(searchValue)
}
},[isWatch, searchValue])
复制代码
计算属性,在React
中我也找到的踪迹
Vue
中的计算属性,相信大家都很熟悉,通常我们会使用计算属性来对template
中的复杂逻辑计算进行简化,比如许多英文网站输入用户名的时候会输入firstName
和lastName
,然后在界面上面又会将firstName
和lastName
连在一起显示,这时候就可以使用到了计算属性对显示进行处理
Vue2.0
中的写法
<template>
<div>
<div>
<label>firstNamelabel>
<input v-model="firstName" />
<label>lastNamelabel>
<input v-model="lastName" />
div>
<div>用户名:{{ name }}div>
div>
template>
<script>
export default {
data() {
return {
firstName: '',
lastName: ''
}
},
computed: {
name() {
return this.firstName + '·' + this.lastName
}
}
}
script>
复制代码
Vue3.0
中的写法
在Vue3.0
的Composition API
也提供了computed API
,用于生成计算属性,用法与Vue2.0
用法基本是一致的
import { computed, defineComponent, reactive } from "vue";
export default defineComponent({
setup() {
const state = reactive({
firstName: "",
lastName: ""
});
const name = computed(() => state.firstName + "·" + state.lastName);
return {
state,
name
};
}
});
复制代码
React
中的写法
在说到在React
中模拟计算属性之前,我们先要了解一些React Hook
的规则。
- 只能在最顶层使用
Hook
- 只能在
React
函数中调用Hook
当我们在React
函数中使用useState
之后,如果我们通过setState
修改了state
,那么这时候react
会做什么呢?React
会将这个函数式组件重新执行一遍,但是对于里面的useState
,useEffect
等等不会重新初始化,而是使用已经记录的状态进行处理。那么React
是怎么知道哪个state
对应哪个useState
呢?答案是React
靠的是Hook
调用的顺序。所以我们不能在非顶层比如if
里面使用Hook
。
同时呢?因为state
的变化会引起整个函数重新执行,那么假如我们在代码里面写了这样一段逻辑
const [firstName, setFirstName] = useState('')
const [lastName, setLastName ] = useState('')
const [other,setOther] = useState('')
// 使用 useMemo可以模仿Vue中的计算属性
const name = firstName + "·" + lastName;
复制代码
上面代码里面我们的name
是通过firstName
与lastName
计算而来的,那么当firstName
或者lastName
发生变化时,都会重新计算name
,这个逻辑是正确的。但是实际上other
如果发生了变化,也会导致name
重新计算,这是我们不愿意看到的。假如name
的计算逻辑很复杂,那么就会引起不必要的性能开支。所以React
提供了useMemo
,用于避免非相关属性变化引起计算逻辑发生变化,而我们正好可以利用useMemo
来模拟计算属性,如下代码
import React, { useMemo, useState } from 'react'
export default function() {
const [firstName, setFirstName] = useState('')
const [lastName, setLastName ] = useState('')
// 使用 useMemo可以模仿Vue中的计算属性,当firstName与`lastName`任何一个发生变化
//都会触发`name`重新计算,但是对于其他属性变化,并不会引起重新计算
const name = useMemo(() => firstName + '·' + lastName,[firstName,lastName])
const handleChange = (method: Function, e: React.ChangeEvent ) => {
method(e.target.value)
}
return (
<div>
<div>
<label>firstNamelabel>
<input
value={firstName}
onChange={(e) => handleChange(setFirstName, e)}
/>
<label>lastNamelabel>
<input
value={lastName}
onChange={(e) => handleChange(setLastName, e)}
/>
div>
<div>用户名:{name}div>
div>
);
}
复制代码
但是呢,在Vue
中计算属性既可以get
,也可以set
,这一点我们是无法使用useMemo
来模拟的,当然如果有小伙伴知道如何模拟,麻烦下方评论区告诉我,谢谢。
总结
作为前端主流三大框架之二的Vue
和React
,在日常工作中还是很常用的,通过这种对比的学习,可以比较好的将两者联合在一起,方便记忆。
作者:前端进击者
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。