⚡ Vue观察者模式实现原理(小白也能懂)
🎯 一句话总结
Vue通过数据劫持 + 观察者模式,实现「数据变 → 自动更新视图」的效果。就像房东装监控,租客登记后,房租涨了自动通知大家!
🛠️ 实现步骤拆解
-
数据劫持(装监控)
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(); // 数据变了!通知所有订阅者 } }); } - 读数据(
-
观察者(租客登记)
- 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]); // 触发视图更新 } } -
触发更新(房东喊话)
当数据被修改(如data.name = "新值"),触发setter→ Dep通知所有Watcher → Watcher执行更新函数(比如重新渲染页面)。
💡 举个栗子
假设页面上有个<div>{{ name }}</div>:
- 第一次渲染:读取
name→ 触发get→ 当前Watcher被登记到Dep。 - 修改数据:
name = "小明"→ 触发set→ Dep通知所有Watcher → 页面<div>更新为“小明”。
🌟 总结
Vue的观察者模式核心是:
- 通过数据劫持监听读写操作。
- Dep统一管理依赖,数据变时批量通知。
- Watcher作为桥梁,连接数据和视图更新。
(就像微信群:房东是数据,群成员是Watcher,房东发消息@所有人,大家立刻同步! )