Vue2 响应式

作者:Administrator 发布时间: 2025-12-19 阅读量:14 评论数:0
<!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>

评论