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

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

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 方法里也添加一个深度监听方法。

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 };

 

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 @ 2023-01-03 14:25  风紧了  阅读(402)  评论(0)    收藏  举报
/* 点击爆炸效果*/ /* 鼠标点击求赞文字特效 */ /*鼠标跟随效果*/