前言 📝
前置知识是要熟悉掌握数据响应式。如果不是很了解可以先去看小编的另外几篇文章。
传送门 🚥🚥🚥: 🥬 建立一个响应式系统
1. 依赖
谁和谁之间有依赖关系?
响应式数据和函数之间有依赖关系。当函数在运行期间用到了响应式数据,那么我们可以称之为两者之间有依赖。
但还有一点需要明确,那就是什么是用到?
所谓用到,是指函数在运行期间出现了读取成员被拦截的情况,这样才算是用到。
完整表述:函数在运行期间,出现了读取响应式数据被拦截的情况,我们就称之为两者之间产生了依赖,这个依赖(也就是一个对应关系)是会被收集的,方便响应式数据发生变化时重新执行对应的函数。
通过下面的伪代码,简单的看一下:
1 2 3 4 5
| var a; function foo() { console.log(a); }
|
1 2 3 4 5
| var a = ref(1); function foo() { console.log(a); }
|
1 2 3 4 5 6 7 8 9 10 11 12
| var a = ref({ b: 1 }); const k = a.value; const n = k.b; function foo() { a; a.value; k.b; n; }
|
总而言之: 只需要判断在函数的运行期间,是否存在读取操作行为的拦截,只要存在这种类型的拦截,那么该函数就和该响应式数据存在依赖关系。
不过,有一种情况需要注意,那就是异步。如果在函数的运行期间存在异步代码,那么之后的代码统统不看了。
1 2 3 4 5 6 7 8 9 10
| var a = ref({ b: 1 }); const k = a.value; const n = k.b; async function foo() { a; a.value; await 1; k.b; n; }
|
2. 函数
函数必须是被监控的函数。
- effect
- watchEffect
- watch
- 组件渲染函数
因此总结一下:只有被监控的函数,在它的同步代码运行期间,读取操作被拦截的响应式数据,才会建立依赖关系,建立了依赖关系之后,响应式数据发生变化,对应的函数才会重新执行。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| import { ref, watchEffect } from "vue"; const state = ref({ a: 1 }); const k = state.value; const n = k.a; watchEffect(() => { console.log("运行"); state; state.value; state.value.a; n; }); setTimeout(() => { state.value = { a: 3 }; }, 500);
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| import { ref, watchEffect } from "vue"; const state = ref({ a: 1 }); const k = state.value; const n = k.a; watchEffect(() => { console.log("运行"); state; state.value; state.value.a; n; }); setTimeout(() => { state.value.a = 1; }, 500);
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| import { ref, watchEffect } from "vue"; const state = ref({ a: 1 }); const k = state.value; const n = k.a; watchEffect(() => { console.log("运行"); state; state.value; state.value.a; n; }); setTimeout(() => { k.a = 2; }, 500);
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| import { ref, watchEffect } from "vue"; let state = ref({ a: 1 }); const k = state.value; const n = k.a; watchEffect(() => { console.log("运行"); state; state.value.a; n; }); setTimeout(() => { state.value.a = 2; }, 500); setTimeout(() => { k.a = 2; }, 1000);
|
1 2 3 4 5 6 7 8 9 10 11 12
| import { ref, watchEffect } from "vue"; const state = ref({ a: 1 }); const k = state.value; const n = k.a; watchEffect(() => { console.log("运行"); state.value.a = 2; }); setTimeout(() => { state.value = {}; }, 500);
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| import { ref, watchEffect } from "vue"; let state = ref({ a: 1 }); const k = state.value; const n = k.a; watchEffect(() => { console.log("运行"); state.value.a; }); setTimeout(() => { state.value = { a: 1 }; }, 500); setTimeout(() => { state.value.a = 2; }, 1000);
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| import { ref, watchEffect } from "vue"; let state = ref({ a: 1 }); const k = state.value; const n = k.a; watchEffect(() => { console.log("运行"); state.value.a; k.a; }); setTimeout(() => { state.value = { a: 1 }; }, 500); setTimeout(() => { k.a = 3; }, 1000); setTimeout(() => { state.value.a = 4; }, 1500);
|
什么时候会产生依赖收集?
只有被监控的函数,在它的同步代码运行期间,读取操作被拦截的响应式数据,才会建立依赖关系,建立了依赖关系之后,响应式数据发生变化,对应的函数才会重新执行。