当前位置:首页 > VUE

vue 观察者实现

2026-01-23 16:09:30VUE

Vue 观察者实现原理

Vue 的观察者模式主要通过 Object.definePropertyProxy 实现数据劫持,结合发布-订阅模式实现响应式更新。

核心实现步骤

数据劫持 通过 Object.definePropertyProxy 拦截对象的读写操作,在属性被访问或修改时触发依赖收集和更新。

function defineReactive(obj, key, val) {
  Object.defineProperty(obj, key, {
    get() {
      console.log(`get ${key}:${val}`);
      return val;
    },
    set(newVal) {
      if (newVal !== val) {
        console.log(`set ${key}:${newVal}`);
        val = newVal;
      }
    }
  });
}

依赖收集 每个响应式属性都有一个对应的 Dep 实例,用于存储所有依赖该属性的 Watcher 对象。

class Dep {
  constructor() {
    this.subscribers = new Set();
  }
  depend() {
    if (activeWatcher) {
      this.subscribers.add(activeWatcher);
    }
  }
  notify() {
    this.subscribers.forEach(watcher => watcher.update());
  }
}

观察者(Watcher) Watcher 实例会在初始化时执行一次回调函数,触发属性的 getter 从而完成依赖收集。

let activeWatcher = null;

class Watcher {
  constructor(vm, fn) {
    this.vm = vm;
    this.fn = fn;
    this.update();
  }
  update() {
    activeWatcher = this;
    this.fn.call(this.vm);
    activeWatcher = null;
  }
}

完整示例

class Vue {
  constructor(options) {
    this._data = options.data;
    this.observe(this._data);
    new Watcher(this, () => {
      console.log('数据变化了', this._data.message);
    });
  }

  observe(data) {
    Object.keys(data).forEach(key => {
      let val = data[key];
      const dep = new Dep();

      Object.defineProperty(data, key, {
        get() {
          dep.depend();
          return val;
        },
        set(newVal) {
          if (newVal !== val) {
            val = newVal;
            dep.notify();
          }
        }
      });
    });
  }
}

const vm = new Vue({
  data: {
    message: 'Hello Vue'
  }
});

vm._data.message = 'Hello World';  // 触发更新

Vue 3 的改进

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

vue 观察者实现

  • 无法检测新增/删除的属性
  • 数组变异方法的拦截
  • 性能更好
function reactive(obj) {
  return new Proxy(obj, {
    get(target, key) {
      track(target, key);
      return target[key];
    },
    set(target, key, value) {
      target[key] = value;
      trigger(target, key);
    }
  });
}

标签: 观察者vue
分享给朋友:

相关文章

vue实现压缩上传文件

vue实现压缩上传文件

压缩上传文件的实现方法 在Vue中实现文件压缩和上传功能,可以通过以下步骤完成。该方法结合了前端文件压缩库和HTTP请求,确保文件在上传前被有效压缩。 安装必要的依赖 需要使用compressorj…

vue实现用户信息表

vue实现用户信息表

Vue 实现用户信息表的方法 使用 Vue CLI 创建项目 安装 Vue CLI 并初始化项目: npm install -g @vue/cli vue create user-info-tabl…

vue实现倒计时抢券

vue实现倒计时抢券

Vue 实现倒计时抢券功能 核心逻辑 倒计时抢券功能需要结合时间计算、状态管理和界面交互。通过 Vue 的响应式特性和生命周期钩子,可以高效实现这一需求。 实现步骤 1. 数据准备 在 Vue 组件…

vue实现文字

vue实现文字

Vue 中实现文字显示的方法 在 Vue 中实现文字显示可以通过多种方式,包括插值表达式、指令、组件等。以下是几种常见的实现方法: 插值表达式 使用双大括号 {{ }} 进行文本插值,这是 Vue…

vue 实现注册

vue 实现注册

Vue 实现注册功能 注册功能通常包括表单验证、数据提交和用户反馈。以下是实现注册功能的步骤: 1. 创建注册表单组件 在 Vue 项目中创建一个注册表单组件,包含用户名、邮箱、密码等输入字段。…

vue 菜单实现

vue 菜单实现

Vue 菜单实现方法 在Vue中实现菜单功能可以通过多种方式完成,以下是几种常见的实现方法: 使用v-for动态生成菜单 通过数据驱动的方式动态渲染菜单项,适合菜单内容可能变化的场景: <t…