专栏导航
分析pinia源码之前必须知道的API
Pinia源码分析【1】- 源码分析环境搭建
Pinia源码分析【2】- createPinia
pinia源码分析【3】- defineStore
pinia源码分析【4】- Pinia Methods
前言
在pinia源码中有一些业务场景下不常用的vue3 api,如果没有预先了解将会给源码解读带来较大困难,建议先搞清楚相关API,阅读代码将会事半功倍~
effectScope
在createPinia
中的遇到的第一行就是不认识的vue3 API,打开官网看了一下,最上方info中写道 effect作用域是一个高阶API,专为库作者服务。
他的作用是创建一片单独的effect
空间,该空间内的effect
将可以一起被处理,有点类似docker
与k8s
的关系,例如ref computed watchEffect
都是docker
中的容器,而effectScope
就是k8s
,它可以统一管理effect
集群。
类型:
1 2 3 4 5 6
| function effectScope(detached?: boolean): EffectScope
interface EffectScope { run<T>(fn: () => T): T | undefined stop(): void }
|
通过官网的类型可以看到,effectScope
存在一个boolean
类型的参数,但是在vue3
文档中并未找到参数说明,而在RFC中找到了更加详细的文档。接下来为effectScope
的相关API说明。
run
接受一个函数并返回该函数的返回值
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| const scope = effectScope(); const counter = ref(1); const setupStore = scope.run(() => { const doubled = computed(() => counter.value * 2); watch(doubled, () => console.log('doubled',doubled.value)); watchEffect(() => console.log("count:", doubled.value)); return { doubled, }; });
console.log(setupStore!.counter.value); setupStore!.counter.value = 2;
|
stop
递归结束所有effect,包括后代effectScope
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| const setupStore = scope.run(() => { const counter = ref(1); const doubled = computed(() => counter.value * 2); nestedScope = effectScope(true ); nestedScope.run(() => { watch(counter, () => console.log("doubled", counter.value * 2)); watchEffect(() => console.log("count:", counter.value*2)); }); return { counter, doubled, }; });
scope.stop(); setupStore!.counter.value = 2;
|
detached
表示是否在分离模式下创建,该参数默认为false
;当为true
的时候,父级被停止,子集也不会受影响。
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
| const scope = effectScope(); let nestedScope: any;
const setupStore = scope.run(() => { const counter = ref(1); const doubled = computed(() => counter.value * 2); nestedScope = effectScope(true ); nestedScope.run(() => { watch(counter, () => console.log("doubled", counter.value * 2)); watchEffect(() => console.log("count:", counter.value * 2)); }); return { counter, doubled, }; });
scope.stop(); setupStore!.counter.value = 2;
nestedScope.stop(); setupStore!.counter.value = 3;
|
markRaw
标记一个对象,使其永远不会转换为 proxy
。返回对象本身。
1 2 3 4 5 6
| const foo = markRaw({}) console.log(isReactive(reactive(foo)))
const bar = reactive({ foo }) console.log(isReactive(bar.foo))
|
markRaw
在pinia
源码中非常常见,主要用于优化pinia的自身性能。
toRaw
toRaw可以获取一个响应式对象的原始属性
1 2 3 4 5 6 7
| const foo = {}; const reactiveFoo = reactive(foo); console.log("toRaw", toRaw(reactiveFoo) === foo);
const foo1 = {}; const refFoo1 = ref(foo1); console.log("toRaw", toRaw(refFoo1.value) === foo1);
|
在pinia
源码中用于获取reactive
的原始数据,并添加字段到其中
toRefs
toRefs
比较常见,简单来说:结果中的每个对象都指向原始属性;在实际开发中常用于reactive的解构。
在pinia
的源码中,针对store
中的state
的处理用到了toRefs
,不过它解构的是state(ref类型)
对象,如果解构的是普通对象将不具备响应式。
结语
以上就是pinia
源码中使用较多的vue3 api
,还有些非常基础的例如ref reactive
,就不做过多赘述了。