实现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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
|
describe("computed", () => {
it("happy path", () => {
const user = reactive({
age: 1,
});
const age = computed(() => {
return user.age;
});
expect(age.value).toBe(1);
});
it("should compute lazily", () => {
// 计算属性的缓存特性
const value = reactive({
foo: 1,
});
const getter = jest.fn(() => {
return value.foo;
});
const cValue = computed(getter);
//cValue.value 就是那个value.foo
// lazy -> 不获取cValue.value,getter就不会执行
expect(getter).not.toHaveBeenCalled();
// 触发cValue.value,get操作后获得1,并且getter执行了
expect(cValue.value).toBe(1);
expect(getter).toHaveBeenCalledTimes(1);
// should not compute again
cValue.value; // get
expect(getter).toHaveBeenCalledTimes(1);
// should not compute until needed
value.foo = 2; // 触发trigger -> 收集effect -> get 重新执行
expect(getter).toHaveBeenCalledTimes(1);
// now it should compute
expect(cValue.value).toBe(2);
expect(getter).toHaveBeenCalledTimes(2);
// should not compute again
cValue.value;
expect(getter).toHaveBeenCalledTimes(2);
});
});
|
分析一下测试用例发现,computed()
和ref()
很像,都是返回一个带有value属性的对象,但是computed()
具有缓存的能力,我们要完善以下细节:
- 接受一个函数,返回一个属性,有个value属性
- 懒执行机制,如果不获取这个value属性,则不执行传递的函数
- 获取了这个value属性后,执行传递的函数一次,并得到返回值
- 再次获取value属性,执行传递的函数一次,不应该计算
- 依赖的值更新后,执行传递的函数一次,获取value属性,传递的函数调用两次
- 再次获取value属性,传递的函数调用两次。
文章作者
吴少林
上次更新
2023-04-02
(1bb8345)
许可协议
MIT