Vue中计算属性和侦听属性的使用

计算属性computed

当需要根据已有的响应式属性计算出一个新的值时,就需要用到计算属性来完成,来降低模板的复杂度。计算属性是基于依赖的响应式数据进行缓存的,在相关响应式依赖发生改变时它们才会重新求值。

使用

// vue2写法简写形式
computed: {
  "计算属性名" () {
    return "值"
  }
}
// 完整形式
computed: {
  "计算属性名" : {
    // getter
    get: function () {
      ......
      return ...
    },
    // setter
    set: function (newValue) {
      ......
    }
  }
}
// vue3写法
import {computed} from 'vue'
//  简写形式
let 属性名 = computed(()=>{
    return ......
})
//完整形式
let 属性名 = computed({
  get(){
    // 该属性值用到的响应式数据发生改变时走get
    return
  },
  set(value){
    // 有响应式用到该属性值,再改属性值改变时走set
    ......
  }
})

侦听属性watch

当需要在响应式属性发生变化时执行一些特定的操作时,可以使用Vue的侦听属性。

使用

//vue2写法
watch: {
  '要侦听的属性名': {
    handler(newValue,oldValue) {
      // 在组件实例创建时会立即调用
    },
    // 强制立即执行回调
    immediate: true,
    //开启深度侦听
    deep:true,
  }
}
//vue3写法,接收三个参数,(要侦听的的属性,回调,配置)
watch(
  person,
  (newValue,oldValue)=>{
  console.log('person变化了',newValue,oldValue)
  },
  {immediate:true,deep:false}
)
# 注意
- 在Vue3中若侦听的是reactive定义的响应式数据,默认开启了深度侦听且不能关闭
- Vue2中watch侦听的,Vue3中若watch侦听的是reactive定义的响应式数据,则无法正确获得oldValue!!!(这是因为复杂类型的数据watch侦听到的新旧值都指向了同一块堆地址)
- 侦听reactive定义的响应式数据中的某一个属性传入的第一个参数需要为`()=>person.job`函数返回值的形式
- 侦听多个属性的话第一个参数应为`[]`数组形式
- 如果侦听的是reactive定义的响应式数据中的一个对象,deep深度侦听属性需要自己开启

解决无法获得oldValue

Vue中计算属性和侦听属性的使用

// 我们只需要将想要侦听的数据在计算属性中将obj进行深拷贝,然后侦听拷贝的内容就可以了(都用到了lodash这个js库)
import {cloneDeep} from 'lodash'
// vue2写法
computed:{
  newobj(){
    return cloneDeep(this.obj)
  }
},
// vue3写法
watch(
  () => _.cloneDeep(obj)
  (newValue,oldValue) => { ...... }
)

Vue中计算属性和侦听属性的使用

watchEffect函数

watchEffect,不用指明侦听哪个属性,监视的回调中用到哪个属性,那就侦听哪个属性,类似计算属性,但computed注重的计算出来的值(回调函数的返回值),所以必须要写返回值,而watchEffect更注重的是过程(回调函数的函数体),不用写返回值。

使用

watchEffect为立即执行函数,类似开启了watch的immediate属性,没有newValue和oldValue,可以手动停止侦听

//watchEffect所指定的回调中用到的数据只要发生变化,则直接重新执行回调。
const textAsync= (number:number)=>{
  return setTimeout(()=>{
    console.log(number); 
  },3000)
}
const watch_Number = watchEffect(async(onCleanup)=>{
  const timer = textAsync(number.value)
  // 只有以来的响应式变量发生变化才会执行
  onCleanup(()=>{
    clearTimeout(timer) //清除定时器
  })
})
setTimeout(_=>{
  number.value++
},2000)
// setTimeout(_=>{
//   watch_Number() // 两秒之后停止侦听
// },2000)

如上代码,模拟访问接口,刚进来的时候number发生变化调用textAsync函数,两秒后number会增加,增加之后又会调用textAsync函数,函数三秒钟后返回数据,这样相当于调用了两次接口,如果加上onCleanup的话就会清除之前内容,只返回最后一次的数据。

小结

用这么久Vue居然才发现这个问题,哈哈哈哈哈,看来要学的东西还很多嘛!

本文正在参加「金石计划」

原文链接:https://juejin.cn/post/7221817362143543356 作者:i东东

(0)
上一篇 2023年4月15日 上午10:30
下一篇 2023年4月15日 上午10:41

相关推荐

发表回复

登录后才能评论