vue2响应式--深度监听模拟

上篇优化了重复的监听,但当data数据为下图一个嵌套数据时,深层嵌套的属性没有响应效果。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import { observe } from "./observer";
import { Watcher } from "./watcher";
 
const data = {
  test: "aa",
  test1: "cc",
  test2: {
    dd: "aa",
  },
};
const recursion = () => {
  console.log(data.test2.dd);
};
observe(data);
new Watcher(recursion);
data.test2.dd = "as"; // 直接修改响应式没有触发
data.test2 = {
  dd: "ss",
}; //整体赋值才有响应效果效果

 我们发现整体赋值才可以有效果,我们就可以在数据劫持时判断当前的key值是否为对象类型,如果为对象类型就调用observe方法,对key值进行响应式。observer.js具体实现如下:

   shallow属性设置数据是否需要深度监听,这样就可以深度监听了,但当我们重新对一个对象赋值后,再修改属性又没有响应效果,所以再set 方法里也添加一个深度监听方法。

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
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
import Dep from "./dep";
const NO_INIITIAL_VALUE = {};
function defineReactive(obj, key, val, shallow) {
  // 获取当前属性有没有自定义方法;
  let property = Object.getOwnPropertyDescriptor(obj, key);
  // 判断当前属性有没有自定义get set 方法
  let getter = property && property.get;
  let setter = property && property.set;
  // 没有val值,去obj里面的
  if (
    (!getter || setter) &&
    (val === NO_INIITIAL_VALUE || arguments.length == 2)
  ) {
    val = obj[key];
  }
 
  const dep = new Dep();
 
  // 如果val值为对象类型,则深度监听
  let childOb = !shallow && observe(val, false);
  Object.defineProperty(obj, key, {
    enumerable: true,
    configurable: true,
    get: function () {
      //添加依赖函数
      if (Dep.target) {
        // dep.addSub(Dep.target);
        dep.depend();
      }
      //如果有自定义方法则调用
      let value = getter ? getter.call(obj) : val;
      return value;
    },
    set: function (newVal) {
      if (setter) {
        setter.call(obj, newVal);
      } else {
        val = newVal;
      }
      // 如果对一个对象整体赋值后,再修改对象属性也没有响应效果,在set也监听下
 
      childOb = !shallow && observe(newVal, false);
      //执行依赖当前属性的依赖函数
      dep.notify();
    },
  });
}
 
export class Observer {
  constructor(data, shallow = false) {
    // shallow 属性判断是否需要深度监听
    this.observer(data, shallow);
  }
  observer(data, shallow) {
    let keys = Object.keys(data);
    for (let key of keys) {
      defineReactive(data, key, NO_INIITIAL_VALUE, shallow);
    }
  }
}
function observe(data, shallow = false) {
  if (typeof data == "object") {
    return new Observer(...arguments);
  } else {
    return false;
  }
}
export { observe };

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import { observe } from "./observer";
import { Watcher } from "./watcher";
 
const data = {
  test: "aa",
  test1: "cc",
  test2: {
    dd: "aa",
  },
};
const recursion = () => {
  console.log(data.test2.dd);
};
 
observe(data);
// 深度响应
new Watcher(recursion);
data.test2.dd = "as";
data.test2 = {
  dd: "ss",
};
data.test2.dd = "111"// 在set里添加深度监听

  

 

posted @   风紧了  阅读(348)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
/* 点击爆炸效果*/
/* 鼠标点击求赞文字特效 */ /*鼠标跟随效果*/
点击右上角即可分享
微信分享提示