JavaScript有一个特性是 Object.defineProperty
,它能做很多事,但我在这篇文章只专注于这个方法中的一个:
rush:js;">
var person = {};
Object.defineProperty (person,'age',{
get: function () {
console.log ("Getting the age");
return 25;
}
});
console.log ("The age is ",person.age);
// Prints:
//
// Getting the age
// The age is 25
(Obeject.defineProperty是Object的一个方法,第一个参数是对象名称,第二个参数是要设置的属性名,第三个参数是一个对象,它可以设置这个属性是否可修改、可写等,而这篇文章主要使用的是Obeject.defineProperty的访问器属性,感兴趣的朋友可以自行google或者查看Js高及程序设计)
尽管 person.age 看起来像是访问了对象的一个属性,但其实在内部我们是运行了一个函数。
一个基本可响应的Vue.js
Vue.js内部构建了一个可以将普通的对象转化为可以被观察的值( 响应属性 ),下面为大家展示一个简化版的如何添加响应属性的案例:
rush:js;">
function defineReactive (obj,key,val) {
Object.defineProperty (obj,{
get: function () {
return val;
},set: function (newValue) {
val = newValue;
}
})
};
// 创建
一个对象
var person = {};
//
添加可响应的
属性"age"和"country"
defineReactive (person,25);
defineReactive (person,'country','Brazil');
// 现在你可以随意使用person.age了
if (person.age < 18) {
return 'mi
nor';
}
else {
return 'adult';
}
// 设置person.country的值
person.country = 'Russia';
有趣的是, 25 和 ‘Brazil' 还是一个闭包内部的变量,只有当赋给它们新值的时候 val 才会改变。 person.country 并不拥有 'Brazil' 这个值,而是getter这个函数拥有 'Brazil' 这个值。
让我们创建一个定义计算属性的函数 defineComputed 。这个函数就跟大家平时使用computed时的一样。
rush:js;">
defineCo
mputed (
person,// 计算
属性就声明
在这个对象上
'status',// 计算
属性的
名称
function () { // 实际返回计算
属性值的
函数
console.log ("status getter called")
if (person.age < 18) {
return 'mi
nor';
}
else {
return 'adult';
}
},function (newValue) {
// 当计算
属性值更新时
调用的
函数
console.log ("status has changed to",newValue)
}
});
// 我们可以像使用一般的
属性一样使用计算
属性
console.log ("The person's status is: ",person.status);
让我们写一个简单的 defineComputed 函数,它支持调用计算方法,但目前不需要它支持 updateCallback 。
rush:js;">
function defineCo
mputed (obj,co
mputeFunc,updateCallback) {
Object.defineProperty (obj,{
get: function () {
// 执行计算
函数并且返回值
return co
mputeFunc ();
},set: function () {
// 什么也不做,不需要设定计算
属性的值
}
})
}
这个函数有两个问题:
每次访问计算属性时都会执行一次计算函数 computeFunc ()
它不知道什么时候更新 (即当我们更新某个data中的属性,计算属性中也会更新这个data属性)
rush:js;">
// 我希望最终
函数执行后是这个
效果:每当person.age更新值的时候,person.status也同步更新
person.age = 17;
// console: status 的值为 mi
nor
person.age = 22;
// console: status 的值为 adult
让我们增加一个全局变量 Dep :
rush:js;">
var Dep = {
target: null
};
这是一个依赖项,接着我们用一个骚操作来更新 defineComputed 函数:
rush:js;">
function defineCo
mputed (obj,updateCallback) {
var onDependencyUpdated = function () {
// T
odo
}
Object.defineProperty (obj,{
get: function () {
// 将onDependencyUpdated 这个
函数传给Dep.target
Dep.target = onDependencyUpdated;
var value = co
mputeFunc ();
Dep.target = null;
},set: function () {
// 什么也不做,不需要设定计算
属性的值
}
})
}
现在让我们回到之前设置的响应属性上:
Object.defineProperty (obj,{
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 ();
});
}
})
};
我们可以在计算属性定义的函数触发更新回调后更新 onDependencyUpdated 函数。
rush:js;">
var onDependencyUpdated = function () {
// 再次计算 计算
属性的值
var value = co
mputeFunc ();
updateCallback (value);
}
把它们整合到一起:
让我们重新访问我们的计算属性 person.status :
18) {
return 'adult';
}
},function (newValue) {
console.log ("status has changed to",newValue)
}
});
console.log ("Status is ",person.status);
总结
以上所述是小编给大家介绍的Vue.js中的computed工作原理。编程之家 jb51.cc 收集整理的教程希望能对你有所帮助,如果觉得编程之家不错,可分享给好友!感谢支持。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。