vue2和vue3的响应式原理有何不同?

简介: 大家好,我是V哥。本文详细对比了Vue 2与Vue 3的响应式原理:Vue 2基于`Object.defineProperty()`,适合小型项目但存在性能瓶颈;Vue 3采用`Proxy`,大幅优化初始化、更新性能及内存占用,更高效稳定。此外,我建议前端开发者关注鸿蒙趋势,2025年将是国产化替代关键期,推荐《鸿蒙 HarmonyOS 开发之路》卷1助你入行。老项目用Vue 2?不妨升级到Vue 3,提升用户体验!关注V哥爱编程,全栈开发轻松上手。

大家好,我是 V 哥。
Vue 2 和 Vue 3 在响应式原理上存在显著差异,下面为你详细介绍。

如果你是前端开发,V 哥建议抓紧入坑鸿蒙,2025年鸿蒙趋势将引领国产化替代的新征程,大量内推岗位等你来拿。

推荐一本鸿蒙 NEXT 书《鸿蒙 HarmonyOS 开发之路》卷1,可以让你少走弯路。

image.png

Vue 2 响应式原理

Vue 2 使用 Object.defineProperty() 方法来实现响应式系统。该方法可以直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回这个对象。

实现原理

  • 核心方法Object.defineProperty() 劫持对象属性的 gettersetter。当一个 Vue 实例创建时,Vue 会遍历 data 选项中的所有属性,使用 Object.defineProperty() 将这些属性转换为 getter/setter
  • 依赖收集:当访问这些属性时,触发 getter,进行依赖收集;当属性值发生变化时,触发 setter,通知所有依赖更新。

示例代码

// 模拟 Vue 2 的响应式原理
function defineReactive(obj, key, val) {
   
    // 存储依赖的数组
    const dep = [];

    Object.defineProperty(obj, key, {
   
        get() {
   
            // 收集依赖
            if (Dep.target) {
   
                dep.push(Dep.target);
            }
            return val;
        },
        set(newVal) {
   
            if (newVal !== val) {
   
                val = newVal;
                // 通知所有依赖更新
                dep.forEach(watcher => watcher.update());
            }
        }
    });
}

// 模拟 Watcher
class Watcher {
   
    constructor() {
   
        Dep.target = this;
    }
    update() {
   
        console.log('数据更新,触发视图更新');
    }
}

// 全局变量,用于存储当前正在收集依赖的 Watcher
Dep.target = null;

// 创建一个对象
const obj = {
   };
// 使对象的属性变为响应式
defineReactive(obj, 'message', 'Hello, Vue 2!');

// 创建一个 Watcher
new Watcher();
// 访问属性,触发 getter 进行依赖收集
console.log(obj.message);

// 修改属性,触发 setter 通知依赖更新
obj.message = 'New message';

局限性

  • 无法检测对象属性的添加和删除:因为 Object.defineProperty() 是对对象已有属性进行劫持,新增或删除属性时无法自动触发响应式更新。
  • 无法检测数组的某些变化:Vue 2 对数组的 pushpop 等方法进行了重写,但对于通过索引直接修改数组元素或修改数组长度的操作无法检测。

Vue 3 响应式原理

Vue 3 使用 ES6 的 Proxy 对象来实现响应式系统。Proxy 对象用于创建一个对象的代理,从而可以对该对象的基本操作进行拦截和自定义。

实现原理

  • 核心方法Proxy 可以拦截对象的各种操作,包括属性读取、属性设置、属性删除等。Vue 3 通过创建一个 Proxy 对象来代理 data 对象,当对代理对象进行操作时,会触发相应的拦截器。
  • 依赖收集和更新:在拦截器中进行依赖收集和更新通知,实现响应式。

示例代码

// 模拟 Vue 3 的响应式原理
function reactive(target) {
   
    // 存储依赖的 WeakMap
    const targetMap = new WeakMap();

    function track(target, key) {
   
        let depsMap = targetMap.get(target);
        if (!depsMap) {
   
            targetMap.set(target, (depsMap = new Map()));
        }
        let dep = depsMap.get(key);
        if (!dep) {
   
            depsMap.set(key, (dep = new Set()));
        }
        if (activeEffect) {
   
            dep.add(activeEffect);
        }
    }

    function trigger(target, key) {
   
        const depsMap = targetMap.get(target);
        if (!depsMap) return;
        const dep = depsMap.get(key);
        if (dep) {
   
            dep.forEach(effect => effect());
        }
    }

    return new Proxy(target, {
   
        get(target, key) {
   
            // 收集依赖
            track(target, key);
            return target[key];
        },
        set(target, key, value) {
   
            target[key] = value;
            // 通知依赖更新
            trigger(target, key);
            return true;
        }
    });
}

// 模拟 effect
let activeEffect;
function effect(fn) {
   
    activeEffect = fn;
    fn();
    activeEffect = null;
}

// 创建一个对象
const obj = {
    message: 'Hello, Vue 3!' };
// 使对象变为响应式
const reactiveObj = reactive(obj);

// 创建一个 effect
effect(() => {
   
    console.log(reactiveObj.message);
});

// 修改属性,触发响应式更新
reactiveObj.message = 'New message';

优势

  • 可以检测对象属性的添加和删除Proxy 可以拦截对象属性的添加和删除操作,从而实现响应式更新。
  • 可以检测数组的所有变化Proxy 可以拦截数组的所有操作,包括通过索引直接修改数组元素和修改数组长度。

所以,Vue 3 的响应式原理相比 Vue 2 更加完善和强大,解决了 Vue 2 中存在的一些局限性。

Vue 2 和 Vue 3 的响应式原理对性能有什么影响?

Vue 2 和 Vue 3 的响应式原理在多个方面对性能产生不同的影响,下面从初始化性能、更新性能、内存占用等方面进行详细分析。

初始化性能

Vue 2

  • 原理特点:Vue 2 使用 Object.defineProperty()data 选项中的每个属性进行递归遍历,并将其转换为 getter/setter。这意味着在初始化时,需要对对象的所有属性进行处理,对于嵌套层级较深的对象,会带来较大的性能开销。
  • 性能影响:当数据对象非常大且嵌套层级很深时,初始化过程会比较耗时,因为需要为每个属性都调用 Object.defineProperty() 方法。例如,一个包含大量嵌套对象和数组的复杂数据结构,初始化时会显著增加 CPU 的计算负担。

Vue 3

  • 原理特点:Vue 3 使用 Proxy 对象来实现响应式。Proxy 是对整个对象进行代理,不需要对每个属性进行递归处理。在初始化时,只需要创建一个 Proxy 对象,当访问对象的属性时才会进行依赖收集。
  • 性能影响:相比 Vue 2,Vue 3 的初始化性能有明显提升,尤其是对于大型数据对象。因为它避免了对所有属性的递归处理,减少了初始化时的计算量。

更新性能

Vue 2

  • 原理特点:当修改 Vue 2 中响应式对象的属性时,会触发 setter 方法,通知所有依赖更新。但由于 Object.defineProperty() 的局限性,对于对象属性的添加和删除以及数组的某些操作(如通过索引直接修改数组元素),无法自动检测,需要使用特殊的方法(如 Vue.setVue.delete)来触发更新。
  • 性能影响:在更新操作时,如果使用不当,可能会导致不必要的更新或无法及时更新。而且,由于依赖收集是基于属性的 gettersetter,对于嵌套层级较深的对象,更新时可能需要层层触发 setter,性能开销较大。

Vue 3

  • 原理特点:Vue 3 的 Proxy 可以拦截对象的各种操作,包括属性的添加、删除和数组的所有操作。当修改响应式对象时,Proxy 会立即捕获到变化,并通知所有依赖更新。
  • 性能影响:Vue 3 的更新性能更加稳定和高效。它能够更准确地检测到对象的变化,避免了 Vue 2 中因操作不当导致的更新问题。同时,由于 Proxy 的拦截机制,更新操作的响应速度更快,减少了不必要的性能损耗。

内存占用

Vue 2

  • 原理特点:由于 Vue 2 需要为每个属性创建 getter/setter,并且需要维护一个依赖收集系统,这会增加额外的内存开销。对于大型数据对象,每个属性都有对应的 getter/setter 和依赖信息,会占用较多的内存空间。
  • 性能影响:在处理大量数据时,Vue 2 的内存占用可能会成为性能瓶颈,尤其是在内存有限的设备上,可能会导致页面卡顿或崩溃。

Vue 3

  • 原理特点:Vue 3 的 Proxy 只需要为整个对象创建一个代理,不需要为每个属性添加额外的 getter/setter,因此内存占用相对较少。同时,Vue 3 的依赖收集系统也进行了优化,减少了不必要的内存开销。
  • 性能影响:Vue 3 在内存使用上更加高效,能够更好地处理大型数据对象,减少了因内存占用过高导致的性能问题。

所以我们可以看到,Vue 3 的响应式原理在初始化性能、更新性能和内存占用方面都优于 Vue 2,尤其是在处理大型数据对象时,性能提升更为明显。

最后

如果你还在老项目中使用 Vue2,V 哥强烈建议更新成 Vue3,老项目的兼容性也许会给你带来一些麻烦,请相信,相比Vue3带来的性能提升,会大大提高系统的用户体验,不防试试。关注威哥爱编程,全栈开发就你行。

相关文章
|
4月前
|
缓存 JavaScript PHP
斩获开发者口碑!SnowAdmin:基于 Vue3 的高颜值后台管理系统,3 步极速上手!
SnowAdmin 是一款基于 Vue3/TypeScript/Arco Design 的开源后台管理框架,以“清新优雅、开箱即用”为核心设计理念。提供角色权限精细化管理、多主题与暗黑模式切换、动态路由与页面缓存等功能,支持代码规范自动化校验及丰富组件库。通过模块化设计与前沿技术栈(Vite5/Pinia),显著提升开发效率,适合团队协作与长期维护。项目地址:[GitHub](https://github.com/WANG-Fan0912/SnowAdmin)。
717 5
|
1月前
|
缓存 前端开发 大数据
虚拟列表在Vue3中的具体应用场景有哪些?
虚拟列表在 Vue3 中通过仅渲染可视区域内容,显著提升大数据列表性能,适用于 ERP 表格、聊天界面、社交媒体、阅读器、日历及树形结构等场景,结合 `vue-virtual-scroller` 等工具可实现高效滚动与交互体验。
217 1
|
1月前
|
缓存 JavaScript UED
除了循环引用,Vue3还有哪些常见的性能优化技巧?
除了循环引用,Vue3还有哪些常见的性能优化技巧?
135 0
|
2月前
|
JavaScript
vue3循环引用自已实现
当渲染大量数据列表时,使用虚拟列表只渲染可视区域的内容,显著减少 DOM 节点数量。
85 0
|
4月前
|
JavaScript API 容器
Vue 3 中的 nextTick 使用详解与实战案例
Vue 3 中的 nextTick 使用详解与实战案例 在 Vue 3 的日常开发中,我们经常需要在数据变化后等待 DOM 更新完成再执行某些操作。此时,nextTick 就成了一个不可或缺的工具。本文将介绍 nextTick 的基本用法,并通过三个实战案例,展示它在表单验证、弹窗动画、自动聚焦等场景中的实际应用。
391 17
|
5月前
|
JavaScript 前端开发 算法
Vue 3 和 Vue 2 的区别及优点
Vue 3 和 Vue 2 的区别及优点
|
5月前
|
存储 JavaScript 前端开发
基于 ant-design-vue 和 Vue 3 封装的功能强大的表格组件
VTable 是一个基于 ant-design-vue 和 Vue 3 的多功能表格组件,支持列自定义、排序、本地化存储、行选择等功能。它继承了 Ant-Design-Vue Table 的所有特性并加以扩展,提供开箱即用的高性能体验。示例包括基础表格、可选择表格和自定义列渲染等。
378 6
|
4月前
|
JavaScript 前端开发 API
Vue 2 与 Vue 3 的区别:深度对比与迁移指南
Vue.js 是一个用于构建用户界面的渐进式 JavaScript 框架,在过去的几年里,Vue 2 一直是前端开发中的重要工具。而 Vue 3 作为其升级版本,带来了许多显著的改进和新特性。在本文中,我们将深入比较 Vue 2 和 Vue 3 的主要区别,帮助开发者更好地理解这两个版本之间的变化,并提供迁移建议。 1. Vue 3 的新特性概述 Vue 3 引入了许多新特性,使得开发体验更加流畅、灵活。以下是 Vue 3 的一些关键改进: 1.1 Composition API Composition API 是 Vue 3 的核心新特性之一。它改变了 Vue 组件的代码结构,使得逻辑组
1468 0
|
6月前
|
JavaScript 前端开发 算法
高效工作流:用Mermaid绘制你的专属流程图;如何在Vue3中导入mermaid绘制流程图
mermaid是一款非常优秀的基于 JavaScript 的图表绘制工具,可渲染 Markdown 启发的文本定义以动态创建和修改图表。非常适合新手学习或者做一些弱交互且自定义要求不高的图表 除了流程图以外,mermaid还支持序列图、类图、状态图、实体关系图等图表可供探索。 博客不应该只有代码和解决方案,重点应该在于给出解决方案的同时分享思维模式,只有思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~
|
6月前
|
JavaScript 前端开发 API
管理数据必备;侦听器watch用法详解,vue2与vue3中watch的变化与差异
一篇文章同时搞定Vue2和Vue3的侦听器,是不是很棒?不要忘了Vue3中多了一个可选项watchEffect噢。 博客不应该只有代码和解决方案,重点应该在于给出解决方案的同时分享思维模式,只有思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~