<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>Vue 2 响应式原理演示</title>
<style>
body { font-family: sans-serif; display: flex; justify-content: center; padding-top: 50px; }
.card { border: 1px solid #ddd; padding: 20px; border-radius: 8px; box-shadow: 0 4px 6px rgba(0,0,0,0.1); }
.count-display { font-size: 24px; color: #42b983; font-weight: bold; }
button { margin-top: 10px; padding: 8px 16px; cursor: pointer; }
</style>
</head>
<body>
<div class="card">
<h2>计数器:<span id="app" class="count-display"></span></h2>
<button id="addBtn">数值 + 1</button>
<p><small>打开控制台查看响应式追踪日志</small></p>
</div>
<script>
// --- 1. 核心响应式逻辑 ---
class Dep {
constructor() {
this.subs = [];
}
addSub(sub) {
this.subs.push(sub);
}
notify() {
this.subs.forEach(sub => sub.update());
}
}
function observe(data) {
if (!data || typeof data !== 'object') return;
Object.keys(data).forEach(key => defineReactive(data, key, data[key]));
}
function defineReactive(obj, key, val) {
const dep = new Dep();
observe(val); // 递归处理子对象
Object.defineProperty(obj, key, {
enumerable: true,
configurable: true,
get() {
if (Dep.target) {
console.log(`[依赖收集] 属性 "${key}" 收集了一个 Watcher`);
dep.addSub(Dep.target);
}
return val;
},
set(newVal) {
if (newVal === val) return;
console.log(`[派发更新] 属性 "${key}" 的值从 ${val} 变为 ${newVal}`);
val = newVal;
observe(newVal);
dep.notify();
}
});
}
class Watcher {
constructor(updateCallback) {
this.updateCallback = updateCallback;
Dep.target = this;
this.updateCallback(); // 触发 get,完成绑定
Dep.target = null;
}
update() {
this.updateCallback();
}
}
// --- 2. 业务逻辑与 DOM 绑定 ---
// 我们的数据模型 (Data Model)
const state = { count: 0 };
// 使数据变为响应式
observe(state);
// 创建一个订阅者,专门负责更新 ID 为 'app' 的元素内容
const displayElement = document.getElementById('app');
new Watcher(() => {
displayElement.innerText = state.count;
});
// 模拟交互:点击按钮修改数据
const btn = document.getElementById('addBtn');
btn.addEventListener('click', () => {
state.count++; // 只需要修改数据,视图会自动变化!
});
</script>
</body>
</html>