计算属性——手写Vue源码漫游(八)
2024-02-24 04:11:03
计算属性
计算属性允许我们在组件中定义依赖于其他数据的属性。当这些依赖数据发生变化时,计算属性也会自动更新。这使得我们可以非常方便地实现一些需要实时更新的数据,比如表单验证、错误信息等。
计算属性的实现原理
计算属性的实现原理其实并不复杂。它主要依靠Vue的响应式系统和watcher来实现。
- 响应式系统:Vue的响应式系统可以自动追踪数据变化,当数据发生变化时,它会通知所有依赖于该数据的watcher。
- watcher:watcher是一个对象,它可以观察一个数据,当这个数据发生变化时,watcher就会执行一个回调函数。
计算属性就是通过创建一个watcher来实现的。当计算属性的依赖数据发生变化时,watcher就会执行一个回调函数,这个回调函数会重新计算计算属性的值,并更新视图。
手写Vue源码中的计算属性
在手写Vue源码中,计算属性的实现主要集中在src/core/instance/state.js
和src/core/instance/computed.js
这两个文件中。
在src/core/instance/state.js
文件中,定义了defineComputed
方法,这个方法用于定义计算属性。
export function defineComputed (
instance,
key,
userDef
) {
const watcher = new Watcher(
instance,
userDef,
null,
{ lazy: true }
)
Object.defineProperty(instance, key, {
get: () => watcher.value,
enumerable: true,
configurable: true
})
}
在defineComputed
方法中,首先创建了一个watcher,这个watcher观察计算属性的依赖数据。然后,在实例上定义一个属性,这个属性的getter函数是watcher的value函数。这样,当计算属性的依赖数据发生变化时,watcher就会执行value函数,重新计算计算属性的值,并更新视图。
在src/core/instance/computed.js
文件中,定义了ComputedWatcher
类,这个类继承自Watcher
类,它专门用于计算属性。
export class ComputedWatcher extends Watcher {
constructor (
vm,
expOrFn,
cb,
options,
isRenderWatcher
) {
super(vm, expOrFn, cb, options, isRenderWatcher)
this.lazy = true
this.dirty = false // for lazy watchers
}
get value () {
const vm = this.vm
if (this.dirty) {
// evaluate the computed value
this.value = this.get()
this.dirty = false
}
return this.value
}
depend () {
const targets = this.dep.target
if (targets) {
targets.addDep(this)
}
}
}
在ComputedWatcher
类中,定义了一个value
属性,这个属性是计算属性的值。当计算属性的依赖数据发生变化时,value
属性就会重新计算。
总结
计算属性是Vue2的响应式系统中一个非常重要的概念,它允许我们在组件中定义依赖于其他数据的属性,当这些依赖数据发生变化时,计算属性也会自动更新。计算属性的实现原理并不复杂,它主要依靠Vue的响应式系统和watcher来实现。