vue-computed实现原理
Posted preciousness
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了vue-computed实现原理相关的知识,希望对你有一定的参考价值。
1,计算属性的用法
vue中计算属性能够实现一个数据依赖其他数据的变化而变化,话不多说先上代码
1 new Vue({ 2 data:{ 3 a:1 4 }, 5 mounted(){ 6 const that = this 7 setTimeout(function(){ 8 that.a = 2 9 },2000) 10 }, 11 computed:{ 12 b:function(){ 13 console.log("现在b的值是",this.a+1) 14 return this.a + 1 15 } 16 } 17 })
在computed中定义一个 计算属性(函数),这个函数中涉及到data中的所有数据,都会被收集起来,将他们作为这个属性计算的依赖,当这些依赖发生变化时,就会执行这个计算属性对应的函数。比如上面的例子中,b的计算属性函数中有this.a,a是data中的数据,那a将会作为b计算属性的一个依赖被收集起来,第8行中that.a = 2,此时a的值发生变化,触发b的计算属性函数,这样就完成了一次计算。
2,计算属性的原理
有这么一个方法 Object.defineProperty()
,先让我们看看这个方法是怎么用的。
Object.defineProperty()
方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。
Object.defineProperty(obj, prop, descriptor)
参数:
obj
要定义属性的对象。prop
要定义或修改的属性的名称或Symbol
。descriptor
要定义或修改的属性描述符。- 其中第三个参数descriptor是一个json,有兴趣的可以去
Object.defineProperty()
研究一下。我们这里主要是看set(属性的setter函数),get(属性的getter函数) - 话不多说,先上代码
var obj = {} Object.defineProperty(obj,"a",{ set:function(val){ console.log("set函数执行") this._a = val // 定义一个_a作为一个私有属性,来记录a属性的值 }, get:function(){ console.log("get函数执行") return this._a } }) obj.a = "123" // set函数执行 console.log(obj.a) // get函数执行 // 123
上面的代码 可以看出 只要执行obj.a = xxx 就会执行 obj中a属性的set函数,只要执行obj.a 就会调用obj中a属性的get函数
3,属性计算的实现
vue中属性计算利用函数闭包和对象属性set,get函数 完美实现
1 var Dep = null 2 function defineReactive(obj,key,val){ 3 var deps = [] // deps 收集依赖用 4 Object.defineProperty(obj,key,{ 5 get:function(){ 6 if(Dep){ 7 deps.push(Dep) 8 } 9 return val 10 }, 11 set:function(newVal){ 12 val = newVal; 13 deps.forEach(func=>func()) // deps 在set函数中被引用 形成闭包 14 } 15 }) 16 } 17 18 function defineComputed(obj,key,func){ 19 func = func.bind(obj) 20 var value 21 Dep = function(){ 22 value = func() // value 在此函数中被引用 形成闭包 23 } 24 value = func() // 执行一次 属性计算函数,计算属性函数中的this.a(36行)的执行,会执行a的get函数(5行),将计算属性函数放到依赖项中(第7行) 25 Dep = null 26 Object.defineProperty(obj,key,{ 27 get:function(){ 28 return value // value 在set函数中被引用 形成闭包 29 } 30 }) 31 } 32 33 var obj = {} 34 defineReactive(obj,"a",0) 35 defineComputed(obj,"b",function(){ 36 var a = this.a 37 return a + 1 38 })
执行上面的代码,在控制台输入
console.log(obj.b)
obj.a += 1;
console.log(obj.b);
obj.a += 1;
console.log(obj.b);
obj.a += 1;
console.log(obj.b);
测试一下,完美打印出 1, 2, 3, 4
通过对存取器属性、闭包和观察者模式的综合运用,Vue 巧妙的实现了计算属性。现在再看官方文档描述,是不是更通透了呢。 可以看出,Vue 响应式系统的核心理念是“依赖”,DOM 节点之所以随数据而变化,是因为节点依赖于数据,计算属性之所以随数据而变化,是因为计算属性依赖于数据。做好响应式的关键就在于处理好依赖关系。
以上是关于vue-computed实现原理的主要内容,如果未能解决你的问题,请参考以下文章