当前位置: 首页 > news >正文

vue2和vue3响应式的区别

Vue 2 的 Object.defineProperty 的局限性

Vue 2 使用 Object.defineProperty 来实现响应式数据,但它有一些明显的局限性:

1. 无法监听属性的添加和删除
  • Object.defineProperty 只能监听已经存在的属性,无法监听动态添加或删除的属性。

  • 例如:

    const obj = { a: 1 };
    Vue.set(obj, 'b', 2); // 需要使用 Vue.set 才能让新属性变成响应式
    delete obj.a; // 需要使用 Vue.delete 才能触发更新
    
2. 无法监听数组的变化
  • Object.defineProperty 无法直接监听数组的变化(如 pushpopsplice 等操作)。

  • Vue 2 通过重写数组的原型方法来实现对数组的监听:

    const arrayProto = Array.prototype;
    const arrayMethods = Object.create(arrayProto);
    ['push', 'pop', 'shift', 'unshift', 'splice', 'sort', 'reverse'].forEach(method => {
        const original = arrayProto[method];
        arrayMethods[method] = function (...args) {
            const result = original.apply(this, args);
            dep.notify(); // 手动触发更新
            return result;
        };
    });
    
3. 性能问题
  • Object.defineProperty 需要递归遍历对象的每个属性,将其转换为响应式数据,这在初始化时会有一定的性能开销。
  • 对于嵌套对象,需要递归监听,性能较差。

Vue 3 的 Proxy 的优势

Vue 3 使用 Proxy 来实现响应式数据,解决了 Vue 2 的许多局限性:

1. 可以监听属性的添加和删除
  • Proxy 可以拦截对象的任意操作,包括属性的添加和删除。

  • 例如:

    const obj = new Proxy({ a: 1 }, {
        get(target, key) {
            console.log(`读取属性 ${key}`);
            return Reflect.get(target, key);
        },
        set(target, key, value) {
            console.log(`设置属性 ${key}${value}`);
            return Reflect.set(target, key, value);
        },
        deleteProperty(target, key) {
            console.log(`删除属性 ${key}`);
            return Reflect.deleteProperty(target, key);
        }
    });
    
    obj.b = 2; // 触发 set
    delete obj.a; // 触发 deleteProperty
    
2. 可以监听数组的变化
  • Proxy 可以直接监听数组的变化,无需重写数组方法。

  • 例如:

    const arr = new Proxy([1, 2, 3], {
        get(target, key) {
            console.log(`读取数组元素 ${key}`);
            return Reflect.get(target, key);
        },
        set(target, key, value) {
            console.log(`设置数组元素 ${key}${value}`);
            return Reflect.set(target, key, value);
        }
    });
    
    arr.push(4); // 触发 set
    
3. 性能更好
  • Proxy 是惰性的,只有在访问属性时才会进行依赖收集,减少了初始化时的性能开销。
  • 对于嵌套对象,Proxy 可以按需监听,性能更好。

Vue 2 和 Vue 3 的对比
特性Vue 2 (Object.defineProperty)Vue 3 (Proxy)
监听属性的添加和删除不支持,需使用 Vue.setVue.delete支持,直接监听
监听数组的变化不支持,需重写数组方法支持,直接监听
性能初始化时需要递归遍历所有属性,性能较差惰性监听,按需收集依赖,性能更好
代码复杂度需要额外处理数组和动态属性代码更简洁,功能更强大
结合代码的梳理
Vue 2 的实现(基于 Object.defineProperty
function observe(obj) {
    for (const key in obj) {
        let internalValue = obj[key];
        let fns = new Set();

        // 递归监听嵌套对象
        if (typeof internalValue === 'object' && internalValue !== null) {
            observe(internalValue);
        }

        Object.defineProperty(obj, key, {
            get() {
                if (activeFunc) {
                    fns.add(activeFunc);
                }
                return internalValue;
            },
            set(val) {
                internalValue = val;
                // 递归监听新值
                if (typeof val === 'object' && val !== null) {
                    observe(val);
                }
                fns.forEach(fn => fn());
            }
        });
    }
}
Vue 3 的实现(基于 Proxy
function reactive(obj) {
    return new Proxy(obj, {
        get(target, key, receiver) {
            const dep = getDep(target, key);
            dep.depend(); // 依赖收集
            const result = Reflect.get(target, key, receiver);
            // 递归监听嵌套对象
            if (typeof result === 'object' && result !== null) {
                return reactive(result);
            }
            return result;
        },
        set(target, key, value, receiver) {
            const dep = getDep(target, key);
            const result = Reflect.set(target, key, value, receiver);
            dep.notify(); // 派发更新
            return result;
        },
        deleteProperty(target, key) {
            const dep = getDep(target, key);
            const result = Reflect.deleteProperty(target, key);
            dep.notify(); // 派发更新
            return result;
        }
    });
}

总结
  • Vue 2 使用 Object.defineProperty,无法监听属性的添加和删除,也无法直接监听数组的变化,需要通过 Vue.set 和重写数组方法来实现。
  • Vue 3 使用 Proxy,可以监听所有操作(包括属性的添加、删除和数组的变化),性能更好,代码更简洁。
  • Proxy 是 Vue 3 响应式系统的核心,它使得 Vue 3 的响应式系统更加灵活和强大。

文章转载自:

http://86HGaPiq.yfpnL.cn
http://7oopLPhA.yfpnL.cn
http://3p91ZiFR.yfpnL.cn
http://GFfjmoVs.yfpnL.cn
http://z5VULdFY.yfpnL.cn
http://obuH2k2P.yfpnL.cn
http://wKFKuJqm.yfpnL.cn
http://LBnf5WpP.yfpnL.cn
http://CMIVhuue.yfpnL.cn
http://DoHBJz7a.yfpnL.cn
http://uMMWS1Pa.yfpnL.cn
http://aG1XoUnN.yfpnL.cn
http://i3BXbTlM.yfpnL.cn
http://KsNB4MjZ.yfpnL.cn
http://wwPU1R8G.yfpnL.cn
http://fMh42UEV.yfpnL.cn
http://2jOS41v3.yfpnL.cn
http://0BFyA3Rb.yfpnL.cn
http://dGEAW0Ko.yfpnL.cn
http://w0lK5W19.yfpnL.cn
http://MBwHhykA.yfpnL.cn
http://wRcm5tjG.yfpnL.cn
http://N7jwBAL8.yfpnL.cn
http://JrOjDyRc.yfpnL.cn
http://ndJu611v.yfpnL.cn
http://x4ah5O0Y.yfpnL.cn
http://ym0fWg1R.yfpnL.cn
http://iIoLkOuZ.yfpnL.cn
http://mIgxOmXR.yfpnL.cn
http://E5w9Fqnk.yfpnL.cn
http://www.dtcms.com/a/36200.html

相关文章:

  • zookeeper从入门到精通
  • LabVIEW Browser.vi 库说明
  • [SWPUCTF 2022 新生赛]ez_rce
  • 前端基础知识
  • 蓝桥杯单片机组第十二届省赛第二批次
  • VMware中安装的ubuntu虚拟机屏幕由居中设置为最大化
  • Dify 工作流分类器技巧
  • LeetCode 热题100 2. 两数相加
  • JS高德地图实现降雨降雪效果
  • DeepSeek开源周Day1:FlashMLA引爆AI推理性能革命!
  • Java 登录框架
  • 模板方法模式
  • 数字信任的底层逻辑:密码学核心技术与现实应用
  • 计算机毕业设计SpringBoot+Vue.js墙绘产品展示交易平台(源码+文档+PPT+讲解)
  • [AI]从零开始的树莓派运行DeepSeek模型教程
  • C#开发——ConcurrentDictionary集合
  • 华为认证考试证书下载步骤(纸质+电子版)
  • docker安装register私库
  • 详解golang的Gengine规则引擎
  • 【排序算法】堆排序详解
  • 基于 SpringBoot 的 “电影交流平台小程序” 系统的设计与实现
  • 推送项目 之 解决冲突
  • Claude 3.7 Sonnet 泄露,Anthropic 最先进 AI 模型即将在 AWS Bedrock 上首次亮相
  • 【NLP 26、实践 ⑥ 引入bert,判断文本中是否有特定字符出现】
  • 深入理解 Redis 设计与集群管理
  • JavaSE学习笔记26-集合(Collection)
  • Unity百游修炼(1)——FootBall详细制作全流程
  • 大模型语料库的构建过程 包括知识图谱构建 垂直知识图谱构建 输入到sql构建 输入到cypher构建 通过智能体管理数据生产组件
  • 【前端基础】Day 1 HTML
  • 【Qt】桌面应用开发 ------ 绘图事件和绘图设备 文件操作