简单讲述Vue 2 响应式原理示例

Vue 2 响应式原理示例

这个示例展示了 Vue 2 中响应式系统的工作原理。下面将详细讲解代码中的各个部分,帮助理解 Vue 2 如何实现数据响应式。

1. 订阅者管理类 Dep

Dep 类用于管理依赖(订阅者),它包含以下几个关键部分:

  • subscribers: 一个 Set 集合,用于存储唯一的订阅者(更新函数)。
  • depend(): 添加当前的依赖到 subscribers 集合中。
  • notify(): 通知所有订阅者调用其更新函数。
class Dep {
    constructor() {
        this.subscribers = new Set(); // 使用 Set 来存储订阅者,确保唯一性
    }

    // 添加订阅者
    depend() {
        if (Dep.target) {
            this.subscribers.add(Dep.target); // 将当前依赖(更新函数)添加到订阅者集合
            console.log(this.subscribers)
        }
    }

    // 通知所有订阅者更新
    notify() {
        this.subscribers.forEach(sub => sub()); // 依次调用所有订阅者的更新函数
    }
}

2. 当前活动的依赖 Dep.target

这是一个全局唯一的变量,用于存储当前的依赖(更新函数)。

Dep.target = null;

3. 将对象的属性转化为响应式 defineReactive

这个函数通过 Object.defineProperty 将对象的属性转换为响应式属性,定义了 gettersetter

  • getter 中,调用 dep.depend() 进行依赖收集。
  • setter 中,调用 dep.notify() 通知所有订阅者更新。
function defineReactive(obj, key) {
    const dep = new Dep();
    let val = obj[key];

    Object.defineProperty(obj, key, {
        enumerable: true,
        configurable: true,
        get() {
            dep.depend(); // 在 getter 中进行依赖收集
            return val;
        },
        set(newVal) {
            val = newVal;
            dep.notify(); // 在 setter 中通知所有订阅者更新
        }
    });
}

4. 观察对象 observe

observe 函数遍历对象的每个属性,并调用 defineReactive 将其转换为响应式属性。

function observe(obj) {
    Object.keys(obj).forEach(key => {
        defineReactive(obj, key);
    });
}

5. 自动运行并追踪依赖 autorun

autorun 函数接收一个更新函数 update,并将其包装在 wrappedUpdate 中。在 wrappedUpdate 中:

  • 设置当前的依赖为 wrappedUpdate
  • 执行更新函数 update 以进行依赖收集。
  • 清空当前的依赖。
function autorun(update) {
    function wrappedUpdate() {
        Dep.target = wrappedUpdate; // 设置当前活动的更新函数
        update(); // 执行更新函数
        Dep.target = null; // 清空当前活动的更新函数
    }
    wrappedUpdate(); // 初次执行,进行依赖收集
}

6. 示例使用

首先定义一个状态对象 state,并使用 observe 函数将其转换为响应式对象。

const state = { message: '你好,宇珩', anotherMessage: '其他消息' };
observe(state);

定义更新函数:

  • updateMessage1updateMessage2 更新页面上的 message
  • updateAnother 更新页面上的 anotherMessage
function updateMessage1() {
    document.getElementById('message1').innerText = state.message;
}

function updateMessage2() {
    document.getElementById('message2').innerText = state.message;
}

function updateAnother() {
    document.getElementById('another').innerText = state.anotherMessage;
}

使用 autorun 函数自动追踪依赖并运行更新函数:

autorun(updateMessage1);
autorun(updateMessage2);
autorun(updateAnother);

最后,添加按钮点击事件以更新状态,从而触发响应式更新:

document.getElementById('updateBtn').addEventListener('click', () => {
    state.message = '更新宇珩'; // 触发更新,调用 updateMessage1 和 updateMessage2
});

document.getElementById('updateAnotherBtn').addEventListener('click', () => {
    state.anotherMessage = '其他更新'; // 触发更新,调用 updateAnother
});

总结

通过以上代码示例,我们详细讲解了 Vue 2 中响应式系统的基本原理和实现方法。这种响应式设计允许数据变化自动更新视图,极大地简化了前端开发过程。

  • 6
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值