实现 computed 计算属性
computed
计算属性只在相关响应式依赖发生改变时它们才会重新求值。如果响应式数据发生变化,则计算属性会依据它所依赖的数据进行重新计算,并拥有缓存机制
单测
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| import { computed } from '../computed' import { reactive } from '../reactive' describe('computed', () => { it('happy path', () => { const user = reactive({ age: 1 }) const age = computed(() => user.age) expect(age.value).toBe(1) }) it('should compute lazily', () => { const value = reactive({ foo: 1 }) const getter = jest.fn(() => value.foo) const cValue = computed(getter) expect(getter).not.toHaveBeenCalled() expect(cValue.value).toBe(1) expect(getter).toHaveBeenCalledTimes(1) cValue.value expect(getter).toHaveBeenCalledTimes(1)
value.foo = 2 expect(getter).toHaveBeenCalledTimes(1)
expect(cValue.value).toBe(2) expect(getter).toHaveBeenCalledTimes(2)
cValue.value expect(getter).toHaveBeenCalledTimes(2) }) })
|
实现单测
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| import { ReactiveEffect } from './effect' class ComputedRefImpl { private _getter: any private _dirty: boolean = true private _value: any private _effect: any constructor(getter) { this._getter = getter this._effect = new ReactiveEffect( getter,
() => { if (!this._dirty) this._dirty = true } ) } get value() {
if (this._dirty) { this._dirty = false this._value = this._effect.run() } return this._value } } export const computed = getter => { return new ComputedRefImpl(getter) }
|
到这里 vue3 的核心响应式功能基本结束了