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。

相关推荐
一只叫煤球的猫3 分钟前
我做了一个“慢慢来”的开源任务管理工具:蜗牛待办(React + Supabase + Tauri)
前端·react.js·程序员
LYFlied6 分钟前
AI时代下的规范驱动开发:重塑前端工程实践
前端·人工智能·驱动开发·ai编程
脾气有点小暴17 分钟前
uniapp开发APP 内嵌外部 HTTPS 链接的实现方案
vue.js·uni-app
CodeCraft Studio19 分钟前
JavaScript图表库 DHTMLX Diagram 6.1 重磅发布:全新PERT模式上线,项目可视化能力再升级!
开发语言·javascript·ecmascript·dhtmlx·图表开发·diagram·javascript图表库
汉得数字平台37 分钟前
汉得H-AI飞码——前端编码助手V1.1.2正式发布:融业务知识,提开发效能
前端·人工智能·智能编码
前端小万37 分钟前
Jenkins 打包崩了?罪魁是 package.json 里的 ^
前端·jenkins
编程小白gogogo37 分钟前
苍穹外卖前端环境搭建
前端
shuaijie051839 分钟前
当表格数据量过大的时候,如何使用不分页进行展示
javascript·vue.js·ecmascript
光影少年41 分钟前
web端安全问题有哪些?
前端·安全
行走的陀螺仪1 小时前
Vite & Webpack 插件/Loader 封装完全指南
前端·webpack·node.js·vite·前端工程化·打包构建