深入解析Vue中的computed工作原理

原创 年树先生 随笔 vue 12246阅读 18 天前 举报

我们通过实现一个简单版的和Vue中computed具有相同功能的函数来了解computed是如何工作的。

JS属性:
JavaScript有一个特性是 Object.defineProperty ,它能做很多事,但我在这篇文章只专注于这个方法中的一个:

(Obeject.defineProperty是Object的一个方法,第一个参数是对象名称,第二个参数是要设置的属性名,第三个参数是一个对象,它可以设置这个属性是否可修改、可写等,而这篇文章主要使用的是Obeject.defineProperty的访问器属性,感兴趣的朋友可以自行google或者查看Js高及程序设计)
尽管 person.age 看起来像是访问了对象的一个属性,但其实在内部我们是运行了一个函数。
一个基本可响应的Vue.js
Vue.js内部构建了一个可以将普通的对象转化为可以被观察的值( 响应属性 ),下面为大家展示一个简化版的如何添加响应属性的案例:

25 和 ‘Brazil' 还是一个闭包内部的变量,只有当赋给它们新值的时候 val 才会改变。 person.country 并不拥有 'Brazil' 这个值,而是getter这个函数拥有 'Brazil' 这个值。
声明一个计算属性
让我们创建一个定义计算属性的函数 defineComputed 。这个函数就跟大家平时使用computed时的一样。

写一个简单的 defineComputed 函数,它支持调用计算方法,但目前不需要它支持 updateCallback

这个函数有两个问题:
每次访问计算属性时都会执行一次计算函数 computeFunc ()
它不知道什么时候更新 (即当我们更新某个data中的属性,计算属性中也会更新这个data属性)

增加一个依赖项
让我们增加一个全局变量 Dep :

这是一个依赖项,接着我们用一个骚操作来更新 defineComputed 函数:

```function defineComputed (obj, key, computeFunc, updateCallback) {
var onDependencyUpdated = function () {
// TODO
}
Object.defineProperty (obj, key, {
get: function () {
// 将onDependencyUpdated 这个函数传给Dep.target
Dep.target = onDependencyUpdated;
var value = computeFunc ();
Dep.target = null;
},//帮助突破技术瓶颈,提升思维能力
set: function () {
// 什么也不做,不需要设定计算属性的值
}
})
}

function defineReactive (obj, key, val) {
// 所有的计算属性都依赖这个数组
var deps = [];
Object.defineProperty (obj, key, {
get: function () {
// 检查是否调用了计算属性,如果调用了,Department.target将等于一个onDependencyUpdated函数
if (Dep.target) {
// 把onDependencyUpdated函数push到deos中
deps.push (target);
}
return val;
},
set: function (newValue) {
val = newValue
// 通知所有的计算属性,告诉它们有个响应属性更新了
deps.forEach ((changeFunction) => {
changeFunction ();
});//欢迎加入全栈开发交流圈一起学习交流:864305860
}//帮助突破技术瓶颈,提升思维能力
})
};

var onDependencyUpdated = function () {
// 再次计算 计算属性的值
var value = computeFunc ();
updateCallback (value);
}

person.age = 22;
defineComputed (
person,
'status',
function () {
if (person.age > 18) {
return 'adult';
}//欢迎加入全栈开发交流圈一起学习交流:864305860
},//帮助突破技术瓶颈,提升思维能力
function (newValue) {
console.log ("status has changed to", newValue)
}
});
console.log ("Status is ", person.status);

评论 ( 0 )
最新评论
暂无评论

赶紧努力消灭 0 回复