vm.$set原理

发布时间 2023-11-17 16:07:29作者: 柯基与佩奇
  1. 给对应和数组本身都增加了 dep 属性
  2. 当给对象新增不存在的属性则触发对象依赖的 watcher 去更新
  3. 当修改数组索引时,调用数组本身的 splice 去更新数组(数组的响应式原理就是重新了 splice 等方法,调用 splice 就会触发视图更新)
splice();
push();
pop();
shift();
unshift();
sort();
reverse();

vue 源码里缓存了 array 的原型链,然后重写了这几个方法,触发这几个方法的时候会 observer 数据,意思是使用这些方法不用再进行额外的操作,视图自动进行更新。 推荐使用 splice 方法会比较好自定义,因为 splice 可以在数组的任何位置进行删除/添加操作

调用方法:Vue.set(target, key, value )
target:要更改的数据源(可以是对象或者数组)
key:要更改的具体数据
value :重新赋的值

<div id="app">{{user.name}} {{user.age}}</div>
<div id="app"></div>
<script>
  // 1. 依赖收集的特点:给每个属性都增加一个dep属性,dep属性会进行收集,收集的是watcher
  // 2. vue会给每个对象也增加一个dep属性
  const vm = new Vue({
    el: "#app",
    data: {
      // vm._data
      user: { name: "poetry" },
    },
  });
  // 对象的话:调用defineReactive在user对象上定义一个age属性,增加到响应式数据中,触发对象本身的watcher,ob.dep.notify()更新
  // 如果是数组 通过调用 splice方法,触发视图更新
  vm.$set(vm.user, "age", 20); // 不能给根属性添加,因为给根添加属性 性能消耗太大,需要做很多处理

  // 修改肯定是同步的 -> 更新都是一步的  queuewatcher
</script>

vm.$set 的实现原理是:

如果目标是数组,直接使用数组的 splice 方法触发相应式;
如果目标是对象,会先判读属性是否存在、对象是否是响应式,最终如果要对属性进行响应式处理,则是通过调用 defineReactive 方法进行响应式处理(defineReactive 方法就是 Vue 在初始化对象时,给对象属性采用 Object.defineProperty 动态添加 getter 和 setter 的功能所调用的方法)