当前位置:首页 > VUE

vue 观察者实现

2026-01-23 16:09:30VUE

Vue 观察者实现原理

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

核心实现步骤

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

vue 观察者实现

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 对象。

vue 观察者实现

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,解决了以下问题:

  • 无法检测新增/删除的属性
  • 数组变异方法的拦截
  • 性能更好
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实现节流的方法 在Vue中实现节流(throttle)功能,通常用于限制高频事件的触发频率,例如滚动、输入或按钮点击。以下是几种常见的实现方式: 使用Lodash的throttle函数 安装L…

vue实现换行

vue实现换行

Vue 中实现换行的几种方法 在 Vue 中实现换行可以通过多种方式,具体取决于使用场景和需求。以下是常见的几种方法: 使用 HTML 的 <br> 标签 在模板中直接使用 <b…

vue实现selectable

vue实现selectable

Vue 实现可选择的 Select 组件 在 Vue 中实现一个可选择的 Select 组件,可以通过以下几种方式: 使用原生 HTML select 元素 <template>…

vue实现swipe

vue实现swipe

Vue实现Swipe功能的方法 使用第三方库(推荐) Vue生态中有多个成熟的轮播/滑动组件库,例如vue-awesome-swiper或swiper/vue。以下是基于swiper/vue的实现示例…

vue实现选择

vue实现选择

Vue 实现选择功能的方法 在 Vue 中实现选择功能可以通过多种方式完成,以下介绍几种常见的实现方法。 使用 v-model 绑定单选 通过 v-model 可以轻松实现单选功能。以下是一个简单的…

vue实现监听

vue实现监听

监听数据变化 在Vue中,可以通过watch选项或$watch方法监听数据的变化。watch适用于组件选项内声明式监听,$watch适用于动态监听。 // 选项式API export defaul…