vue|源码篇|watch及computed的实现

848 阅读2分钟

前言

  • 本文是vue|源码篇|1.0版本数据观测 依赖收集的续版,如果有vue数据驱动、依赖收集理解基础的同学可以直接上手,如无,建议阅读上篇文章
  • 文章结构采用【指出阶段目标,然后以需解决问题为入口,以解决思路为手段】达到本文目标,若使诸君稍有启发,不枉此文心力^-^

目标

实现watch
  • 属性改变,会触发watch中定义的函数执行
  • watch多个写法的实现
实现computed
  • 以computed中属性对应函数返回值为属性值
  • computed缓存特性,即多次取同一属性,当其依赖属性未改变时不会重新计算

实现watch和computed

核心:一定要理解,页面渲染是取值操作,会触发数据属性的get

实现watch 很精妙 (精美)

核心思路:取值会触发属性的get,从而将当前的计算属性watcher存入当前监听的属性的dep中,并记录当前值;下一次再触发时,如果是计算属性Watcher(user:true),则将新老值传递给回调并执行

实现computed 更有趣(更难懂。。)

核心:默认不执行,当取值时会触发computed属性的get方法(需新定义),如果dirty为true(计算属性的标识是lazy)则执行exec方法求值;求值时会触发被依赖属性的get方法,从而将当前的计算属性watcher存入被依赖属性的dep中,

问题
  1. computed与watch相比的差别是什么?都说computed有缓存,是指什么?怎么实现的

    1. 用户取值才执行
    2. 默认取老值,依赖值更改时才重新取新值
  2. 大家有没有注意到,如果被依赖属性没有在页面取值,也就是她的dep中并不会存入渲染watcher,那就会导致,其实页面并不会更新,怎么解决?

    1. 在计算属性的get中进行判断,如果Dep.target 不为空,即为渲染watcher,那就将这个watcher存入被依赖属性中即可
小结
  1. watch其实就是预定义的this.$watch

  2. computed 属性 是有节流效果的

  3. 这两者的实现都是基于依赖收集的,或者说是对watcher和dep的巧妙应用

多则惑少则得,如果只能记住一句话:watch的多个定义格式巧用很方便
。。。深度观测
obj:{
			handler(newValue, oldValue) {
				//do something
				console.log(newValue,oldValue)
			},
			deep:true
		}

。。。立即执行
obj:{
			handler(newValue, oldValue) {
				//do something
				console.log(newValue,oldValue)
			},
			deep:true,
			immediate: true
		}
。。。。。观测对象中的某个属性
"obj.acount":{
			handler(newValue, oldValue) {
				//do something
				console.log(newValue,oldValue)
			},
			deep:true,
			immediate: true
		}