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。

相关推荐
a濯2 小时前
element plus el-table多选框跨页多选保留
javascript·vue.js
蓝婷儿2 小时前
前端面试每日三题 - Day 32
前端·面试·职场和发展
星空寻流年3 小时前
CSS3(BFC)
前端·microsoft·css3
九月TTS3 小时前
开源分享:TTS-Web-Vue系列:Vue3实现固定顶部与吸顶模式组件
前端·vue.js·开源
H309193 小时前
vue3+dhtmlx-gantt实现甘特图展示
android·javascript·甘特图
CodeCraft Studio3 小时前
数据透视表控件DHTMLX Pivot v2.1发布,新增HTML 模板、增强样式等多个功能
前端·javascript·ui·甘特图
一把年纪学编程3 小时前
【牛马技巧】word统计每一段的字数接近“字数统计”
前端·数据库·word
llc的足迹3 小时前
el-menu 折叠后小箭头不会消失
前端·javascript·vue.js
九月TTS4 小时前
TTS-Web-Vue系列:移动端侧边栏与响应式布局深度优化
前端·javascript·vue.js
曾经的你d4 小时前
【electron+vue】常见功能之——调用打开/关闭系统软键盘,解决打包后键盘无法关闭问题
vue.js·electron·计算机外设