当前位置:首页 > VUE

vue watch 实现 原理

2026-01-15 05:06:48VUE

Vue Watch 实现原理

Vue 的 watch 功能用于监听数据变化并执行回调函数。其核心原理基于 Vue 的响应式系统,依赖 Object.definePropertyProxy(Vue 3)实现数据劫持,并结合依赖收集和派发更新机制。

响应式系统基础

Vue 的响应式系统通过以下步骤实现:

  1. 数据劫持:使用 Object.defineProperty(Vue 2)或 Proxy(Vue 3)拦截数据的读取和修改操作。
  2. 依赖收集:在数据被访问时,收集当前正在计算的依赖(如 watch 回调)。
  3. 派发更新:在数据被修改时,通知所有依赖执行更新。

Watch 的工作流程

  1. 初始化阶段
    当在 Vue 实例中定义 watch 时,Vue 会遍历 watch 的配置项,为每个被监听的数据创建一个 Watcher 实例。

    new Vue({
      data: { count: 0 },
      watch: {
        count(newVal, oldVal) {
          console.log('count changed:', oldVal, '->', newVal);
        }
      }
    });
  2. 依赖收集
    Watcher 实例会在初始化时调用 get 方法,触发被监听数据的 getter,从而将当前 Watcher 添加到依赖列表中(Dep 的 subs 数组)。

  3. 数据变化触发回调
    当被监听的数据被修改时,会触发 setterProxy 的拦截逻辑,通知依赖列表中的所有 Watcher 执行 update 方法。
    Watcherupdate 方法会调用回调函数,并传入新值和旧值。

源码核心逻辑(Vue 2)

  1. Watcher 类
    Watcherwatch 的核心实现,负责管理依赖和回调执行。

    class Watcher {
      constructor(vm, expOrFn, cb, options) {
        this.vm = vm;
        this.cb = cb;
        this.getter = parsePath(expOrFn); // 解析监听路径(如 'a.b.c')
        this.value = this.get(); // 初始化时触发依赖收集
      }
    
      get() {
        pushTarget(this); // 将当前 Watcher 设置为全局正在计算的依赖
        const value = this.getter.call(this.vm, this.vm); // 触发 getter
        popTarget(); // 恢复之前的依赖
        return value;
      }
    
      update() {
        const oldValue = this.value;
        this.value = this.get(); // 重新获取值
        this.cb.call(this.vm, this.value, oldValue); // 执行回调
      }
    }
  2. 依赖管理(Dep 类)
    每个响应式数据属性都有一个 Dep 实例,用于管理依赖。

    class Dep {
      constructor() {
        this.subs = []; // 存储 Watcher 实例
      }
    
      depend() {
        if (Dep.target) {
          this.subs.push(Dep.target); // 收集依赖
        }
      }
    
      notify() {
        this.subs.forEach(watcher => watcher.update()); // 通知更新
      }
    }

深度监听和立即执行

  1. 深度监听(deep: true)
    通过递归遍历对象的所有属性,为每个子属性绑定 Watcher

    if (this.deep) {
      traverse(value); // 递归触发子属性的 getter
    }
  2. 立即执行(immediate: true)
    Watcher 初始化时直接调用回调。

    if (options.immediate) {
      cb.call(vm, this.value);
    }

Vue 3 的改进

Vue 3 使用 Proxy 替代 Object.defineProperty,解决了以下问题:

  • 无需递归劫持对象,Proxy 可以动态监听新增属性。
  • 性能更好,避免了 Vue 2 中全量递归的缺陷。

总结

Vue 的 watch 机制依赖于响应式系统的核心设计:

vue watch 实现 原理

  • 通过 WatcherDep 管理依赖关系。
  • 数据变化时触发 Watcher 回调。
  • 支持深度监听和立即执行等高级功能。

标签: 原理vue
分享给朋友:

相关文章

vue实现贴图

vue实现贴图

Vue 实现贴图功能 在Vue中实现贴图功能通常涉及将图片动态添加到指定位置或元素上。以下是几种常见实现方式: 使用v-bind动态绑定图片 通过数据驱动的方式动态更换图片源: <templ…

vue grid实现

vue grid实现

Vue Grid 实现方法 在 Vue 中实现网格布局可以通过多种方式完成,包括使用原生 CSS Grid、第三方组件库或自定义组件。以下是几种常见方法: 使用原生 CSS Grid 通过 Vue…

vue 简单实现

vue 简单实现

以下是 Vue 的简单实现示例,涵盖基础模板、数据绑定、方法及生命周期: 基础模板与数据绑定 <div id="app"> <p>{{ message }}</…

vue实现翻页

vue实现翻页

Vue实现翻页功能 在Vue中实现翻页功能通常需要结合分页组件和数据请求逻辑。以下是常见的实现方法: 使用Element UI分页组件 安装Element UI后,可以直接使用其分页组件:…

vue实现幻灯

vue实现幻灯

Vue实现幻灯片的基础方法 使用Vue实现幻灯片功能可以通过多种方式完成,以下是几种常见方案: 方案一:基于Vue的过渡动画 通过Vue的<transition>或<transit…

vue 实现穿透

vue 实现穿透

Vue 样式穿透的实现方法 在 Vue 中,样式穿透通常指在带有 scoped 属性的样式块中,强制影响子组件的样式。以下是几种常见的实现方式: 使用 >>> 或 /deep/ 选…