当前位置:首页 > 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中实现右下角弹框,通常需要结合CSS定位和Vue的组件化特性。弹框可以通过绝对定位固定在右下角,并通过Vue控制其显示与隐藏。 创建弹框组件 新建一个Vue组件(如…

vue实现弹幕

vue实现弹幕

Vue 实现弹幕功能 弹幕功能通常包括动态生成、滚动显示、颜色和速度随机化等特性。以下是基于 Vue 3 的实现方法。 核心思路 使用 CSS 动画控制弹幕从右向左滚动。 动态生成弹幕数据,随机设置…

vue nexttick实现

vue nexttick实现

Vue 中 nextTick 的实现原理 Vue 的 nextTick 是一个用于在下次 DOM 更新循环结束之后执行延迟回调的方法。它的核心实现依赖于 JavaScript 的事件循环机制。 基本…

vue实现横滚

vue实现横滚

Vue 实现横滚效果 横滚效果通常指水平滚动内容,常见于轮播图、横向导航栏等场景。以下是几种实现方式: 使用 CSS 和 Vue 结合 通过 CSS 的 overflow-x 和 white-spa…

vue 分页 实现

vue 分页 实现

Vue 分页实现方法 使用第三方库(如 Element UI) Element UI 提供了现成的分页组件 el-pagination,适合快速集成。 安装 Element UI: npm ins…

vue实现 treegrid

vue实现 treegrid

Vue 实现 TreeGrid 的方法 使用现成组件库 Element UI、Ant Design Vue 等流行组件库提供了现成的 TreeTable/TreeGrid 组件,可直接使用。 Ele…