Vue观察者模式实现原理(小白也能懂)

84 阅读2分钟

⚡ Vue观察者模式实现原理(小白也能懂)


🎯 一句话总结

Vue通过数据劫持 + 观察者模式,实现「数据变 → 自动更新视图」的效果。就像房东装监控,租客登记后,房租涨了自动通知大家!


🛠️ 实现步骤拆解

  1. 数据劫持(装监控)
    Vue用Object.defineProperty()(Vue2)或Proxy(Vue3)给数据属性(如data.name)加监听。

    • 读数据get):记录谁在“看”这个数据(例如页面上的{{ name }})。
    • 改数据set):发现数据变了,立刻通知所有“看”它的人。
    // 简化示例:劫持数据属性  
    function defineReactive(obj, key) {  
      let value = obj[key];  
      const dep = new Dep(); // 创建“通知中心”  
        
      Object.defineProperty(obj, key, {  
        get() {  
          if (Dep.target) { // 如果有人在读取这个属性(比如页面渲染)  
            dep.addSub(Dep.target); // 把“订阅者”登记到通知中心  
          }  
          return value;  
        },  
        set(newVal) {  
          if (newVal === value) return;  
          value = newVal;  
          dep.notify(); // 数据变了!通知所有订阅者  
        }  
      });  
    }  
    
  2. 观察者(租客登记)

    • Dep(通知中心) :管理所有订阅者(Watcher),数据变时批量通知。
    • Watcher(订阅者) :每个被数据绑定的地方(如{{ name }})对应一个Watcher,负责触发更新。
    // 通知中心(类似房东的电话本)  
    class Dep {  
      constructor() {  
        this.subs = [];  
      }  
      addSub(sub) {  
        this.subs.push(sub);  
      }  
      notify() {  
        this.subs.forEach(sub => sub.update());  
      }  
    }  
    
    // 订阅者(每个关注数据的“租客”)  
    class Watcher {  
      constructor(vm, key, updateFn) {  
        this.vm = vm;  
        this.key = key;  
        this.updateFn = updateFn;  
        Dep.target = this; // 标记自己是当前订阅者  
        this.vm[this.key]; // 触发getter,登记到Dep  
        Dep.target = null; // 重置  
      }  
      update() {  
        this.updateFn.call(this.vm, this.vm[this.key]); // 触发视图更新  
      }  
    }  
    
  3. 触发更新(房东喊话)
    当数据被修改(如data.name = "新值"),触发setter → Dep通知所有Watcher → Watcher执行更新函数(比如重新渲染页面)。


💡 举个栗子

假设页面上有个<div>{{ name }}</div>

  1. 第一次渲染:读取name → 触发get → 当前Watcher被登记到Dep。
  2. 修改数据name = "小明" → 触发set → Dep通知所有Watcher → 页面<div>更新为“小明”。

🌟 总结

Vue的观察者模式核心是:

  • 通过数据劫持监听读写操作。
  • Dep统一管理依赖,数据变时批量通知。
  • Watcher作为桥梁,连接数据和视图更新。

就像微信群:房东是数据,群成员是Watcher,房东发消息@所有人,大家立刻同步!