一篇文章弄懂vue的响应式原理。写了很久的vue也应该了解一下响应式原理了(含代码)

Vue.js 是一个流行的前端框架,它以数据驱动和组件化的开发方式著称。Vue 的响应式系统是其核心特性之一,它能够让数据的变化自动反映到视图上,极大地简化了界面开发的复杂度。

在 Vue 2.x 中,响应式系统的实现依赖于 Object.defineProperty() 方法。通过这个方法,Vue 在初始化实例时对 data 对象的每个属性进行处理,转换成 getter/setter,并收集依赖,以便在属性被访问和修改时通知变化。

下面我们将从源码的角度分析 Vue 的响应式原理。

1.初始化阶段

当你创建一个新的 Vue 实例时,Vue 会调用 initData() 函数来初始化实例的数据。在 initData() 函数中,Vue 会遍历 data 对象中的所有属性,并使用 defineReactive() 函数将每个属性转换为 getter/setter。

function defineReactive(obj, key, val) {
  const dep = new Dep();

  Object.defineProperty(obj, key, {
    enumerable: true,
    configurable: true,
    get: function reactiveGetter() {
      if (Dep.target) {
        dep.addSub(Dep.target);
      }
      return val;
    },
    set: function reactiveSetter(newVal) {
      if (newVal === val) return;
      val = newVal;
      dep.notify();
    }
  });
}

2.依赖收集

Dep 是一个用来管理依赖的类,它维护了一个数组,用来存储所有订阅了数据变化的 watcher 实例。在 getter 中,如果存在一个正在计算的 watcher,那么这个 watcher 将被添加到依赖列表中。这个过程称为“依赖收集”。

class Dep {
  constructor() {
    this.subs = [];
  }

  addSub(sub) {
    this.subs.push(sub);
  }

  notify() {
    this.subs.forEach(sub => {
      sub.update();
    });
  }
}

3.派发更新

当数据变化时,setter 会被触发。在 setter 中,新值会被保存,并且调用 dep.notify() 来通知所有依赖进行更新。notify() 会遍历所有的 watcher 实例,并调用它们的 update() 方法。

watcher.update = function () {
  /* ... */
  queueWatcher(this);
};

function queueWatcher(watcher) {
  /* ... */
  nextTick(flushSchedulerQueue);
}

queueWatcher() 函数负责将 watcher 放入一个队列中,然后 nextTick() 会在下一个 tick 中处理这个队列。这样做的目的是为了避免不必要的重复渲染,即在同一个事件循环中,只有当所有数据变化都完成后,才会执行实际的 DOM 更新。

4.异步更新队列

Vue 使用异步队列来控制 DOM 的更新时机。这意味着在同一事件循环中,无论一个数据属性被修改多少次,实际上它只会导致一次 DOM 更新。这种机制是通过 nextTick()flushSchedulerQueue() 实现的。

function flushSchedulerQueue() {
  let watcher, id;

  for (index = 0; index < queue.length; index++) {
    watcher = queue[index];
    id = watcher.id;
    has[id] = null;
    watcher.run(); // 执行 watcher 的 run 方法,进而触发 updateComponent
  }

  /* ... 清空队列等操作 ... */
}

Vue.prototype.$nextTick = function (fn) {
  return nextTick(fn, this);
};

$nextTick() 方法允许你在下一个 DOM 更新循环之后执行回调,这对于想要在数据变化之后立即操作 DOM 的情况非常有用。

总结

Vue 的响应式系统是通过对象属性的 getter/setter 来追踪变化的。当数据变化时,相关的依赖会被通知,视图也会相应地更新。这个过程涉及到依赖收集、派发更新和异步队列更新等关键步骤,确保了数据和视图的同步以及高效的更新策略。

需要注意的是,在 Vue 3.x 中,响应式系统的实现有了较大的变化,引入了 Proxy 对象来实现更为精细和高效的响应式追踪。

以上就是 Vue 2.x 中响应式系统的基本原理和源码解析。希望这篇文章能帮助你更好地理解 Vue 的响应式机制,并在实际开发中更加得心应手。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

蓝斑.json

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值