导读
watch、watchEffect、计算属性
watch函数
- 监视reactive定义的响应式数据 时:oldValue无法正确获取,强制开启了深度监视(deep配置失效)
- 如果实在需要oldValue,那么就要把监视的属性放到ref里定义
- 监视reactive定义的响应式数据中moused属性时,deep配置有效
<template> <h1>子组件</h1> <h2>当前求和:{{sum}}</h2> <h2>当前消息:{{msg}}</h2> <button @click="sum++">点我+1</button> <button @click="msg+= '!'">点我该消息</button> <h2>姓名:{{person.name}}</h2> <h2>年龄:{{person.age}}</h2> <button @click="person.name += '~'">修改名字</button> </template> <script> import {reactive,ref,watch} from 'vue' export default { name: 'Demo', setup(props,context) { //数据 let sum =ref(0) let msg = ref('您好') let person = reactive({ name:'wxl', age:18, job:{ 1:{ sex:'男' } } }) //情况1:监视ref所定义的一个响应式数据,newValue和oldValue本身就会是value值的本身了 // watch(sum,(newValue,oldValue)=>{ // console.log('sum变了',newValue,oldValue) // },{immediate:true,}) //情况2:监视 ref所定义的多个响应式数据 // watch([sum,msg],(newVale,oldValue)=>{ // console.log('sum或msg变了 ',newVale,oldValue) // }) //情况3:监视reactive所定义的一个响应式数据全部数据,但是无法正确获得oldValue, //且newValue和oldValue本身就会是reactive对象了 // watch(person,(newValue,oldValue)=>{ // console.log('person变化了 ',newValue,oldValue) // },{deep:false,}) //此处的deep配置无效 //情况四:监视reactive所定义的一个响应式数据中的某个属性(name),即getter函数 // watch(()=>person.name,(newValue,oldValue)=>{ // console.log('person的name变化了',newValue,oldValue) // }) //情况5:监视reactive所定义的一个响应式数据中的某些属性 // watch([()=>person.name,()=>person.age],(newValue,oldValue)=>{ // console.log('person的name或age变化了',newValue,oldValue) // }) //特殊情况(对照情况3) watch(()=>person.job,(newValue,oldValue)=>{ console.log('person的job变化了',newValue,oldValue) },{deep:true}) //由于监视的是reactive所定义的对象中的某个属性(属性要是对象),所以deep配置有效,深度监听 return{ sum, msg } } } </script>
watchEffect函数
- watch:既要指明监视的属性,也要指明监视的回调
- watchEffect:不用指明监视哪个属性,监视的回调中用到了哪个属性,那就监视哪个属性。
- watchEffect与computed
- computed注重计算出来的值(回调函数的返回值)
- watchEffect更注重的是过程(回调函数的函数体),所以不用写返回值
watchEffect(()=>{ const x1 = sum.value const x2 = person.age console.log('watchEffect配置的回调执行了') })
watchEffect清除副作用
- 在开发中,有时候需要在侦听函数中执行网络请求,但是在网络请求还没有到达的时候,我们停止了侦听器或者侦听器函数被再次执行了
- 那么上一次的网络请求应该被取消掉,即清除上一次的副作用。
在给watchEffect传入的函数被调用的时候,可以获取到一个参数:onInvalidate
- 当副作用即将重新执行或者侦听器被停职是会执行该函数传入的回调函数。
- 然后我们可以在传入的回调函数中,执行一些清除工作。
const stop = watchEffect((onInvalidate)=>{ const timer = setTimeout(()=>{ console.log('网络请求成功') },2000) onInvalidate(()=>{ // 在这个函数中清除额外的副作用,比如 // clearTimeout(timer) //或者 request.cancel() }) //只要count发生变化,就会发起网络请求 console.log('count:',count.value) }) const btn=()=>{ count.value++; if(count.value>10){ //手动停止侦听器 stop() } }
计算属性
计算属性本身是一个ref值
<template> <h1>子组件</h1> 姓:<input type="text" v-model="person.firstName"> <br> 名:<input type="text" v-model="person.lastName"> <br> 全名:<input type="text" v-model="person.fullName"> </template> <script> import {reactive,computed} from 'vue' export default { name: 'Demo', // emits:['hello'] setup(props,context) { //数据 let person = reactive({ firstName:'王', lastName:'学龙' }) //计算属性--简写(不考虑计算属性被修改的情况) // person.fullName = computed(()=>{ // return person.firstName + '-'+person.lastName // }) //计算属性--完整写法(考虑读和写的情况) person.fullName = computed({ get(){ //读 return person.firstName + '-'+person.lastName }, set(value){ //写,这样的话修改fullName,也会改变firstName的值 const nameArr = value.split('-') person.firstName = nameArr[0] person.lastName = nameArr[1] } }) return{ person } } } </script>