Vue3如何实现响应式

回顾Vue2.x的Object.define Property

关于vue2的响应式实现可以看下我的另一篇文章:vue2响应式的实现一机Object.defineProperty的缺点

学习proxy语法

基本使用

javascript 复制代码
const data = {
    a: 1,
    b: '20',
    c: [1, 2, 3]
}

const proxyData = new Proxy(data, {
    get(target, key, receiver) {
        // 只处理本身(非原型)数据
        if (Reflect.ownKeys(target)) {
            console.log('keys', Reflect.ownKeys(target));
        }
        const result = Reflect.get(target, key, receiver);
        console.log('get', key);
        return result;
    },
    set(target, key, value, receiver) {
        // 重复数据,不处理
        const oldValue = target[key];
        if (oldValue === value) {
            return true;
        }
        console.log('set', key, value)
        const result = Reflect.set(target, key, value, receiver);
        return result;
    },
    deleteProperty(target, key) {
        console.log('delete', key)
        const result = Reflect.deleteProperty(target, key);
        return result;
    }
})

Reflect

  • 和proxy能力一一对应
  • 规范化、标准化、函数式
  • 代替Object上的工具函数

实现响应式

Vue如何用proxy实现响应式

废话不多说,直接上代码

javascript 复制代码
const data = {
    a: 1,
    b: '20',
    c: {
        d: {
            e: [1, 2, 3]
        }
    },
    info: {
        name: 'wenrenfangge'
    }
}

function reactive(target = {}) {
    if (target == null || typeof target !== "object") {
        return target;
    }
    const config = {
        get(target, key, receiver) {
            // 只处理本身(非原型)数据
            const ownKeys = Reflect.ownKeys(target)
            if (ownKeys.includes(key)) {
                console.log('已有的key:', key);
            } else {
                console.log('新增的key:', key);
            }
            const result = Reflect.get(target, key, receiver);
            console.log('get', key);
            return reactive(result);
        },
        set(target, key, value, receiver) {
            // 重复数据,不处理
            const oldValue = target[key];
            if (oldValue === value) {
                return true;
            }
            if (ownKeys.includes(key)) {
                console.log('已有的key:', key);
            } else {
                console.log('新增的key:', key);
            }
            console.log('set', key, value)
            const result = Reflect.set(target, key, value, receiver);
            return result;
        },
        deleteProperty(target, key) {
            console.log('delete', key)
            const result = Reflect.deleteProperty(target, key);
            return result;
        }
    }
    return new Proxy(target, config);
}

const proxyData = reactive(data);
  • 深度监听,性能更好
  • 可监听新增/删除属性
  • 可监听数组变化

Proxy能规避Object.defineProperty的问题,但是无法兼容所有浏览器,无法polyfill。

相关推荐
Pedro2 分钟前
Flutter - 日志不再裸奔:pd_log 让打印有型、写盘有序
前端·flutter
申阳3 分钟前
Day 3:01. 基于Nuxt开发个人呢博客项目-初始化项目
前端·后端·程序员
三小河8 分钟前
解决 React + SSE 流式输出卡顿:Nginx 关键配置实战
前端·架构·前端框架
玖月晴空17 分钟前
Uniapp 速查文档
前端·微信小程序·uni-app
琉-璃19 分钟前
vue3+ts 任意组件间的通信 mitt的使用
前端·javascript·vue.js
FogLetter37 分钟前
React Fiber 机制:让渲染变得“有礼貌”的魔法
前端·react.js
不想说话的麋鹿43 分钟前
「项目前言」从配置程序员到动手造轮子:我用Vue3+NestJS复刻低代码平台的初衷
前端·程序员·全栈
JunpengHu1 小时前
esri-leaflet介绍
前端
胖虎2651 小时前
Vue3 多入口项目实战:如何优雅管理多个独立业务模块
vue.js
zm4351 小时前
bpmn.js 自定义绘制流程图节点
前端·bpmn-js