读该文章之前,你需要先了解Proxy相关的知识。
最近读vue3源码,isRef使用了一个其实非常非常简单的办法。
比如下面这段代码:
1 2 3 4 5 6 7
| class Ref { public __v_isRef = true } function ref(val) { return new Ref() }
|
若你想判断obj是否是ref,其实很简单:
1 2 3 4 5 6
| function isRef(value) { return !!value.__v_isRef } const obj = ref(18) isRef(obj) isRef({})
|
但isReactive和isReadonly不太一样。他们俩会先设定好一个map:
1 2 3 4 5 6 7 8 9 10
| export const ReactiveFlags = { IS_REACTIVE: '__v_isReactive', IS_READONLY: '__v_isReadonly', } function isReactive(raw) { return !!raw[ReactiveFlags.IS_REACTIVE] } export function isReadonly(raw) { return !!raw[ReactiveFlags.IS_READONLY] }
|
然后,如果你调用isReactive,就会去触发get:
1 2 3 4
| const obj = reactive({ age: 18 }) isReactive(obj)
|
接着,在Proxy get里面,单独对该key做一个判断,如果访问的是该key,就return true:
1 2 3 4
| if (key === ReactiveFlags.IS_REACTIVE) { return true }
|
这里get返回true,因此isReactive返回true。(并且Proxy get后续代码不需要执行。也就是说,如果是访问了__v_isReactive这个字段,直接return true)
1 2 3 4
| const obj = reactive({ age: 18 }) isReactive(obj)
|
说到这里,再来一个computed的简易原理:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| class ComputedRefImpl { private getter: Function constructor(getter) { this.getter = getter } get value() { return this.getter() } }
export function computed(getter: Function) { const computedRef = new ComputedRefImpl(getter) return computedRef }
const user = reactive({ age: 1, }) const computedAge = computed(() => { return user.age })
|
computed里面的回调函数会返回一个值,然后在ComputedRefImpl类中get value返回该函数的值,最终,当你使用computedAge.value的时候就会去触发get,获取该callback的返回值。