← 返回目录

第 8 卷

第 8 / 8 卷日期:

13const effectFn = () => {

14//执行副作用函数前,清除该函数在所有依赖中的记录(避免重复收集)
15cleanup(effectFn);
16activeEffect = effectFn; //标记当前活跃的副作用函数
17fn(); //执行副作用函数,触发Proxy的get拦截,进行依赖收集
18activeEffect = null; //收集完成后清空标记
19};
20//初始化执行一次副作用函数
21effectFn();
22 }

23 24/**

25* 清除副作用函数的依赖记录

26* @param {Function} effectFn -要清除的副作用函数
27*/
28function cleanup(effectFn) {
29//遍历targetMap,找到所有包含当前effectFn的依赖集合并删除
30for (const [target, keyMap] of targetMap) {
31for (const [key, effects] of keyMap) {
32effects.delete(effectFn);
33}
34}
35}

36 37/**

38* 依赖收集:在响应式数据被访问时调用 39* @param {Object} target - 目标对象

40* @param {string|symbol} key -被访问的属性名
41*/
42function track(target, key) {
43//若没有活跃的副作用函数,无需收集依赖
44if (!activeEffect) return;

45

46// 1.从targetMap中获取目标对象对应的keyMap(属性-副作用映射)
47let keyMap = targetMap.get(target);
48if (!keyMap) {
49targetMap.set(target, (keyMap = new Map()));
50}
52// 2.从keyMap中获取属性对应的副作用集合
53let effects = keyMap.get(key);
54if (!effects) {

60} 61

62/** 63* 触发更新:在响应式数据被修改时调用

64* @param {Object} target - 目标对象

65* @param {string|symbol} key -被修改的属性名
66*/
67function trigger(target, key) {
68// 1.从targetMap中获取目标对象对应的keyMap
69const keyMap = targetMap.get(target);
70if (!keyMap) return;

71 72// 2. 获取属性对应的副作用集合

73const effects = keyMap.get(key);

74if (!effects) return;

75

76// 3.执行所有副作用函数(创建新数组避免遍历中删除元素导致的问题)
77[...effects].forEach(effectFn => effectFn());
78}

79 80/**

81* 创建响应式对象(核心:Proxy代理)

82* @param {Object} target -要代理的目标对象
83* @returns {Proxy}响应式代理对象
84*/
85function reactive(target) {
86//校验:只代理对象/数组(基本类型无需代理)
87if (target === null || typeof target !== 'object') {
88return target;

补充总结(新增3道面试题)

  1. 事件总线(EventBus):基于发布-订阅模式,核心是维护事件注册表,提供on/emit/off/once方

法,实现组件解耦通信

  1. 函数柯里化(curry):将多参数函数转化为单参数函数序列,通过闭包保存已接收参数,参数足够

时执行原函数,支持分步传参和this绑定

  1. Vue3响应式:核心是Proxy代理+Reflect操作,配合effect/track/trigger实现依赖收集和更新触

发,解决了Vue2的数组/新增属性响应式缺陷,依赖存储用WeakMap避免内存泄漏

(注:文档部分内容可能由 AI 生成)

全站分卷索引 · 8 卷
  1. 1第 1 卷
  2. 2第 2 卷
  3. 3第 3 卷
  4. 4第 4 卷
  5. 5第 5 卷
  6. 6第 6 卷
  7. 7第 7 卷
  8. 8第 8 卷