在学习Vue框架的时候,学到了计算属性这个内容,书上说,在计算属性里写一个get函数,然后读取属性值的时候,就会调用到get函数。那么,这个过程是怎么实现的呢?get函数不是自己写的吗?为什么vue知道要去调用这个函数呢?
在vue2中,这个get是Object.defineProperty()中的一个访问器属性,任何一个变量都会有set/get/value/write这样的四个内置属性,在给变量赋值的时候会触发set,在访问变量的值的时候会触发get。Object.defineProperty则是可以修改这四个内置属性。vue2正式通过数据劫持实现这个过程。
vue3中则是通过proxy拦截get操作。以下给一个Object.defineProperty的例子。
var obj = {}; // Creates a new object 创造对象
Object.defineProperty(obj, "hello", {
get: function () {
console.log('触发了get')
return "123"
},
})
console.log(obj.hello)
//先打印 触发了get
// 再打印 123
不知道你这个问题是否已经解决, 如果还没有解决的话:当对观察目标进行求值的时候,肯定会触发数据的getter函数
get: function reactiveGetter () {
// 获取值
const value = getter ? getter.call(obj) : val
// 判断是否有Dep.target 如果有就代表Dep添加了Watcher实例化对象
if (Dep.target) {
// 加入到dep去管理watcher
dep.depend()
// 如果存在子对象
if (childOb) {
// 也加进去管理
childOb.dep.depend()
// 如果值是数组,要特殊处理
if (Array.isArray(value)) {
// 循环添加watcher
dependArray(value)
}
}
}
return value
},
进入get后,判断Dep.target是否存在,此时Dep.target是存在的,因为我们执行了this.get方法内部的pushTarget,此时Dep.target就是一个Watcher实例,因此会执行dep.depend()
// 添加watcher
// 为Watcher.newDeps.push(dep) 一个dep对象
depend () {
// target就是Watcher dep就是dep对象,dep中是否有watcher对象
if (Dep.target) {
// 用当前的watcher调用addDep
// :todo 为了多对多关系,得分析addDep
Dep.target.addDep(this)
}
}
Vue框架中,当定义一个计算属性并定义了get函数时,当读取计算属性时,Vue会自动调用这个get函数。这个get函数必须是自己定义的,且必须符合Vue的语法规范,格式类似于下面这样:
computed: {
myComputedProp: {
get: function () {
// 计算逻辑
return result;
},
set: function (newValue) {
// 设置逻辑
// 注意:如果没有定义set函数,这个计算属性就是只读的
}
}
}
上面这段代码定义了一个计算属性myComputedProp
,其中get
函数用于计算属性值,set
函数用于设置计算属性值。其中newValue
是你要设置的新值。如果只需要计算属性,而不需要设置属性,可以不定义set
函数。
Vue框架中,get
函数必须是符合Vue语法规范的函数。如果不符合规范,Vue将无法识别这个函数,也就无法正确获取计算属性的值。例如,下面的代码定义了一个计算属性,但是get函数没有返回任何值:
computed: {
myComputedProp: {
get: function () {
console.log('计算属性被计算了');
}
}
}
这个代码虽然没有语法错误,但是get函数没有返回值,无法正确计算计算属性的值。当你使用这个计算属性的时候,Vue会不停地计算属性值,因为这个属性值始终是undefined。
需要注意的是,get函数虽然可以自己定义,但是必须遵守Vue的语法规范。在Vue的文档中,有详细的计算属性规范,包括了这个函数的参数、作用域、依赖项等等。如果你不熟悉Vue的语法规范,建议先学习一下Vue的文档。
参考资料: https://cn.vuejs.org/v2/guide/computed.html https://cn.vuejs.org/v2/api/#computed https://www.jianshu.com/p/5cd2bd2f5fc5