Vue2 源码探究响应式原理

简介: 【8月更文挑战第28天】Vue2 源码探究响应式原理

Vue.js 的响应式系统是它的核心特性之一,它允许开发者以声明式的方式将数据渲染到 DOM 上,并在数据变化时自动更新视图。Vue 2 中的响应式系统主要通过 Object.defineProperty 方法来实现,这一方法允许在对象上定义或修改属性的 getter/setter。接下来,我将通过代码示例和解释来阐述 Vue 2 中的响应式原理。

1. 响应式数据的基础:Object.defineProperty

Vue 2 使用 Object.defineProperty 来劫持对象属性的 getter 和 setter,以便在访问或修改这些属性时执行特定的逻辑(如依赖收集、派发更新等)。

function defineReactive(obj, key, val) {
   
    // 递归处理子对象
    observe(val);

    // 创建一个依赖收集器
    const dep = new Dep();

    // 使用 Object.defineProperty 定义响应式属性
    Object.defineProperty(obj, key, {
   
        enumerable: true,
        configurable: true,
        get: function reactiveGetter() {
   
            // 依赖收集
            const target = Dep.target;
            if (target) {
   
                dep.depend();
                if (isArray(val)) {
   
                    dependArray(val);
                }
            }
            return val;
        },
        set: function reactiveSetter(newVal) {
   
            // 新的值与旧值相同时不处理
            if (newVal === val) return;
            // 递归设置子对象的响应性
            observe(newVal);
            // 派发更新
            dep.notify();
            val = newVal;
        }
    });
}

// 依赖收集器
class Dep {
   
    constructor() {
   
        this.subscribers = new Set();
    }
    depend() {
   
        if (Dep.target) {
   
            this.subscribers.add(Dep.target);
        }
    }
    notify() {
   
        this.subscribers.forEach(sub => sub.update());
    }
}

// 全局变量,用于依赖收集
Dep.target = null;

// 观察一个对象
function observe(value) {
   
    if (!isObject(value) || value instanceof VNode) {
   
        return;
    }
    Object.keys(value).forEach(key => {
   
        defineReactive(value, key, value[key]);
    });
}

// 辅助函数
function isObject(value) {
   
    return value !== null && typeof value === 'object';
}

2. 组件的响应式更新

在 Vue 组件中,data 里的属性会被转换成响应式数据。当这些属性在模板中被访问时,Vue 会使用 Dep.target 来标记当前正在计算的 watcher(通常是渲染 watcher)。

// 假设的组件初始化
function initComponent(component) {
   
    const data = component.data();
    observe(data);
    // 假设的渲染函数
    function render() {
   
        Dep.target = new Watcher(component, function updateComponent() {
   
            // 渲染逻辑
        });
        // 访问响应式数据,触发 getter
        console.log(data.message);
        Dep.target = null;
    }
    render();
}

// 简单的 Watcher 类
class Watcher {
   
    constructor(vm, cb) {
   
        this.cb = cb;
        this.vm = vm;
        this.deps = [];
        this.get(); // 触发 getter,进行依赖收集
    }
    get() {
   
        Dep.target = this;
        // 假设的访问响应式数据
        // this.vm.data.message;
        Dep.target = null;
    }
    update() {
   
        this.cb();
    }
}

总结

上述代码展示了 Vue 2 中响应式系统的基础实现。通过 Object.defineProperty,Vue 能够拦截对对象属性的访问和修改,从而执行依赖收集和派发更新等操作。在组件的渲染过程中,Vue 会利用 Dep.target 来标记当前正在计算的 watcher,并在访问响应式属性时通过 getter 进行依赖收集。当响应式数据变化时,setter 会被触发,进而通知所有依赖该数据的 watcher 执行更新操作,实现视图的自动更新。

虽然这个示例较为简化,但它捕捉了 Vue 2 响应式系统的核心思想和关键步骤。在实际应用中,Vue 还会处理更复杂的场景,如数组变化检测、计算属性、侦听器等。

目录
相关文章
|
缓存 监控 JavaScript
Vue响应式原理的10个细节
Vue响应式原理的10个细节
51 0
|
4月前
|
设计模式 JavaScript 前端开发
Vue响应式原理全解析
Vue的响应式系统是其核心特性之一,它使得Vue能够以高效的方式响应数据的变化。通过对对象属性的getter和setter进行劫持,Vue实现了对数据变化的侦测和依赖收集,当数据变化时能够自动派发更新。Vue3中,响应式系统得到了进一步的加强和优化,使用Proxy替代了 `Object.defineProperty`,带来了更好的性能和更强大的拦截能力。理解Vue的响应式原理,对于深入理解Vue的工作机制和进行高效的Vue开发都具有重要意义。
51 1
|
7月前
|
JavaScript 前端开发
解释 Vue 的响应式系统原理。
解释 Vue 的响应式系统原理。
92 0
|
7月前
|
JavaScript 前端开发 算法
探究前端框架Vue.js的响应式原理
本文将深入探讨前端框架Vue.js的核心特性——响应式原理。我们将介绍Vue.js中的数据绑定、依赖追踪和虚拟DOM等概念,并通过具体的示例代码解析其工作机制。通过了解Vue.js的响应式原理,开发者可以更好地利用这一特性构建灵活、高效的前端应用。
|
7月前
|
JavaScript API
【源码&库】跟着 Vue3 的源码学习 reactive 背后的实现原理
【源码&库】跟着 Vue3 的源码学习 reactive 背后的实现原理
83 0
手写vue3核心源码——响应式原理(Computed篇)
手写vue3核心源码——响应式原理(Computed篇)
|
JavaScript
如何才能了解VUE基础呢?来这篇文章告诉你。
如何才能了解VUE基础呢?来这篇文章告诉你。
91 1
|
JavaScript 算法 前端开发
深入vue2.0源码系列:手写代码模拟Vue2.0实现虚拟DOM的实现原理
深入vue2.0源码系列:手写代码模拟Vue2.0实现虚拟DOM的实现原理
107 0
|
存储 JavaScript 对象存储
深入vue2.x源码系列:手写代码来模拟Vue2.x的响应式数据实现
深入vue2.x源码系列:手写代码来模拟Vue2.x的响应式数据实现
88 0
|
测试技术
手撸vue3核心源码——响应式原理(ref)
手撸vue3核心源码——响应式原理(ref)