本文已参与【新人创作礼】活动,一起开启掘金创作之旅。
引言:Vue3中的计算属性
computed和监视watch与Vue2中的配置功能一致,但监视watch在用的时候却存在两个小坑,而且Vue3出现了watchEffect函数,能够更智能化去监视一个对象,下面与小编一起学习探讨一下吧。
一、计算属性computed
Vue3中的computed与Vue2中的功能一致,分简单写法(默认只能get)与完成写法(既能get也能set),大家可根据以下代码进行验证,此处不过多赘述。
<template>
<h1>一个人的信息</h1>
姓:<input type="text" v-model="person.firstName">
名:<input type="text" v-model="person.lastName">
<h2>全名:{{person.fullName}}</h2>
<br/>
全名<input type="text" v-model="person.fullName">
</template>
<script>
import {computed, reactive} from 'vue'
export default {
name: 'Demo',
setup(){
let person = reactive({
firstName:'张',
lastName:'三'
})
// 计算属性-简单:只能获取不能修改
// person.fullName = computed(()=> {
// return person.firstName + '-' + person.lastName
// })
// 计算属性-完整:既能get也能set
person.fullName = computed({
get () {
return person.firstName + '-' + person.lastName
},
set (value) {
const nameArr = value.split('-')
person.firstName = nameArr[0]
person.lastName = nameArr[1]
}
})
return {
person
}
}
}
</script>
二、监视watch
1、先简单回顾一下Vue2的watch写法
Vue2中的watch为对象类型,每个属性可做监视,同时immediate、deep可对监视状态进行调整;
watch: {
firstName : {
immediate:true, // 在刷新页面时先执行一次监视
deep:true, // 深层监听,为了发现对象内部值的变化,此处不考虑是否对象,只做展示
handler (val) {
this.fullName = val + ' ' + this.lastName
}
},
}
2、重点说下Vue3的watch用法
语法:watch(source,callback,object)
-
source:监视的属性。当监视属性为基础数据类型时,为String;当监视属性为对象中的某个属性时,为Function;当同时监视多个属性时,可使用数组形式。 -
callback:监视的回调。回调函数中有两个参数,newValue和oldValue。 -
object:最后参数为对象类型,里边可以传immediate、deep。
- 通过一个简单案例看一下watch最简单用法
<template>
<h2>当前求和为:{{sum}}</h2>
<button @click="sum++">点我+1</button>
<hr>
<h2>当前的信息为:{{msg}}</h2>
<button @click="msg+='!'">修改信息</button>
<hr>
<h2>姓名:{{person.name}}</h2>
<h2>年龄:{{person.age}}</h2>
<h2>薪资:{{person.job.j1.salary}}K</h2>
<button @click="person.name+='~'">修改姓名</button>
<button @click="person.age++">增长年龄</button>
<button @click="person.job.j1.salary++">涨薪</button>
</template>
<script>
import {watch, reactive, ref} from 'vue'
export default {
name: 'Demo',
setup(){
let sum = ref(0)
let msg = ref('你好啊')
let person = reactive({
name:'张三',
age:18,
job:{
j1:{
salary:20
}
}
})
// 情况一:监视ref所定义的一个响应式数据
watch(sum,(newValue,oldValue) => {
console.log(newValue,oldValue)
},{immediate:true})
return {
sum,
msg,
person
}
}
}
</script>
因为开启了immediate,所以一进页面先监听一次,往后没点一次按钮数字加1,请看效果图:
- 情况二:监视ref所定义的多个响应式数据.此时属性放在一个数组中
watch([sum,msg],(newValue,oldValue) => {
console.log('sum或msg变了',newValue,oldValue)
})
先点【点我+1】按钮,对应回调参数返回的数组第一个数据变化,又点【修改信息】,随之第二个属性变化。请看效果图:
3. 情况三:监视reactive所定义的一个响应式数据的全部属性
watch(person,(newValue,oldValue)=>{
console.log('person变化了',newValue,oldValue)
},{deep:false}) //此处的deep配置无效
-
注意1:此处无法正确的获取
oldValue。无论是点击【修改姓名】【增长年龄】【涨薪】均获取不到正确的oldValue -
注意2:强制开启了深度监视(deep配置无效)。
job值还是能被监视到
4. 情况四:监视reactive所定义的一个响应式数据中的某个属性
watch(() => person.name , (newValue,oldValue) => {
console.log('person的name变化了',newValue,oldValue)
})
此时的oldValue可以正常获取到,观察是否名称增加了 ~,但oldValue没有变化
5. 情况五:监视reactive所定义的一个响应式数据中的某些属性
watch([()=>person.name,()=>person.age],(newValue,oldValue)=> {
console.log('person的name或age变化了',newValue,oldValue)
})
监视对账中的多个属性时,用数组加方法形式进行传值,同时回调里的新旧值还是在一个数组里呈现出来,请看效果图:
6. 特殊情况:监视reactive所定义的一个响应式数据中的一个属性,且这个属性也是对象类型
// 为防止大家遗忘,将person数据源放在此处
let person = reactive({
name:'张三',
age:18,
job:{
j1:{
salary:20
}
}
})
// 监视person中的job也是一个对象类型
watch(()=>person.job,(newValue,oldValue)=>{
console.log('person的job变化了',newValue,oldValue)
},{deep:true})
-
注意1:监视person中的job也是一个对象类型
-
注意2:此处无法正确的获取oldValue
-
注意3:此处由于监视的是reactive素定义的对象中的某个属性,所以deep配置有效 请看效果图:
如上图展示,点击【涨薪】按钮后,newValue和oldValue值一样,oldValue无法获取之前的20
将deep改为false后,将监视不到job值变化
watch(()=>person.job,(newValue,oldValue)=>{
console.log('person的job变化了',newValue,oldValue)
},{deep:false})
一直点【涨薪】按钮,数据变化没有检测到,控制台并没有打印出数据
三、watchEffect函数
-
watch的套路是:既要指明监视的属性,也要指明监视的回调。
-
watchEffect的套路是:不用指明监视哪个属性,监视的回调中用到哪个属性,那就监视哪个属性。
-
watchEffect有点像computed:
- 但computed注重的计算出来的值(回调函数的返回值),所以必须要写返回值。
- 而watchEffect更注重的是过程(回调函数的函数体),所以不用写返回值。
//watchEffect所指定的回调中用到的数据只要发生变化,则直接重新执行回调。
watchEffect(()=>{
console.log('sum.value',sum.value)
console.log('person.job.j1.salary',person.job.j1.salary)
console.log('watchEffect所指定的回调执行了')
})