vue computed和watch详解

1.概念

computed(计算属性)和watch(监听器)都是以vue的依赖追踪机制为基础的,当依赖数据发生变化时,依赖此数据的相关数据会自动变化

2.应用场景

computed处理场景:一个数据受多个数据的影响;watch处理场景:一个数据影响多个数据

  • 当我们需要进行数值计算,并且依赖于其它数据时,应该使用 computed,因为可以利用 computed 的值有缓存的特性,避免每次获取值时,都要重新计算;所以如果v-if涉及较多的数值计算,用computed性能会比v-if更好 不需要每次重新计算

  • 当我们需要在数据变化时执行异步或开销较大的操作时,应该使用 watch,使用 watch 选项允许我们执行异步操作 ( 访问一个 API ),限制我们执行该操作的频率,并在我们得到最终结果前,设置中间状态。这些都是计算属性无法做到的。

3.原理

watch实现过程:

  • watch的初始化在data初始化之后(此时的data已经通过Object.defineProperty的设置成响应式)
  • watch的key会在Watcher里进行值的读取,也就是立马执行get获取value(从而实现data对应的key执行getter实现对于watch的依赖收集),此时如果有immediate属性那么立马执行watch对应的回调函数
  • 当data对应的key发生变化时,触发user watch实现watch回调函数的执行

computed实现过程:

  1. 当组件初始化的时候,computeddata会分别建立各自的响应系统,Observer遍历data中每个属性设置get/set数据拦截
  2. 初始化computed会调用initComputed函数

    1. 注册一个watcher实例,并在内实例化一个Dep消息订阅器用作后续收集依赖(比如渲染函数的watcher或者其他观察该计算属性变化的watcher
    2. 调用计算属性时会触发其Object.definePropertyget访问器函数
    3. 调用watcher.depend()方法向自身的消息订阅器depsubs中添加其他属性的watcher
    4. 调用watcherevaluate方法(进而调用watcherget方法)让自身成为其他watcher的消息订阅器的订阅者,首先将watcher赋给Dep.target,然后执行getter求值函数,当访问求值函数里面的属性(比如来自dataprops或其他computed)时,会同样触发它们的get访问器函数从而将该计算属性的watcher添加到求值函数中属性的watcher的消息订阅器dep中,当这些操作完成,最后关闭Dep.target赋为null并返回求值函数结果。
  3. 当某个属性发生变化,触发set拦截函数,然后调用自身消息订阅器depnotify方法,遍历当前dep中保存着所有订阅者wathcersubs数组,并逐个调用watcher的 update方法,完成响应更新。

4.demo

computed:根据不同状态展示不同文案

<div>{{getAlertText}}</div>
    data() {
      return {
        alertText: 0,
      };
    },
    computed: {
      getAlertText() {
        let text = [
          '为了您的账户安全,请先完成实名认证,并设置资金密码',
          '为了您的账户安全,请先设置资金密码',
          '为了您的账户安全,请先完成实名认证',
        ];
        return text[this.alertText];
      }
    },
    methods: {
      preCheckAccount() {
        this.$_http.preCheckAccount().then(res => {
          this.alertText = res.alertText
        });
      },
    }

watch:监听输入值的变化

<input type="text" v-model="childrens.name" />
      data() {
        return {
          childrens: {
            name: '小强',
            age: 20
          },
          lastName:"张三"
        }
      },
      watch:{
        childrens:{
          handler (val,oldval){
            console.log(`对象属性name由${oldval.name}变为${val.name}`)
          },
          deep:true//对象内部的属性监听,也叫深度监听,当使用deep watch的时候监听器会给对象的所有属性加上监听器,增大性能开销。如果这里不加,是监听不到childrens的变化的
        },
        //键路径必须加上引号
        'childrens.name' (val,oldval){
          console.log(`name由${oldval.name}变为${val.name}`)
        }
      },

 

  • 0
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值