vue3实现响应式原理-Proxy

vue3:

  • ts重写(响应式, vdom, 模板编译)
  • 性能提升, 打包后代码量减少
  • 调整部分API

回顾 Object.definePropery 的缺点

  • 深度监听需要一次性递归
  • 无法监听新增属性和删除属性(Vue.$set Vue.delete)
  • 无法原生监听数组, 需要特殊处理(重写数组原型)

Proxy实现响应式

1. 基本使用
const data = {
    name: 'zhangsan',
    age: '20',
}
const data = ['a', 'b', 'c']

const proxyData = new Proxy(data, {
    get(target, key, receiver) {
        // 只处理本身(非原型的)属性
        const ownKeys = Reflect.ownKeys(target)
        if (ownKeys.includes(key)) {
            console.log('get', key) // 监听
        }

        const result = Reflect.get(target, key, receiver)
        return result // 返回结果
    },
    set(target, key, val, receiver) {
        // 重复的数据,不处理
        if (val === target[key]) {
            return true
        }

        const result = Reflect.set(target, key, val, receiver)
        console.log('set', key, val)
        // console.log('result', result) // true
        return result // 是否设置成功
    },
    deleteProperty(target, key) {
        const result = Reflect.deleteProperty(target, key)
        console.log('delete property', key)
        // console.log('result', result) // true
        return result // 是否删除成功
    },
})

2. Reflect 作用
  • 和proxy能力一一对应
  • 规范化, 标准化, 函数式
  • 替代掉Object上的工具函数(未来)
const obj = {a:1,b:2}

//等价
'a' in obj 
Reflect.has(obj,'a')

//等价
delete obj.a
Reflect.deleteProperty(obj,'a')

//等价
Object.getOwnPropertyNames(obj) //['a','b']
Reflect.ownKeys(obj)

详细可以查阅ES6的 代理与反射

vue3 怎么用Proxy实现响应式的

// 创建响应式
function reactive(target = {}) {
    if (typeof target !== 'object' || target == null) {
        // 不是对象或数组,则返回
        return target
    }

    // 代理配置
    const proxyConf = {
        get(target, key, receiver) {
            // 只处理本身(非原型的)属性
            const ownKeys = Reflect.ownKeys(target)
            if (ownKeys.includes(key)) {
                console.log('get', key) // 监听
            }

            const result = Reflect.get(target, key, receiver)

            // 深度监听
            // 性能如何提升的?不是一次性递归的
            return reactive(result)
        },
        set(target, key, val, receiver) {
            // 重复的数据,不处理
            if (val === target[key]) {
                return true
            }

            const ownKeys = Reflect.ownKeys(target)
            if (ownKeys.includes(key)) {
                console.log('已有的 key', key)
            } else {
                console.log('新增的 key', key)
            }

            const result = Reflect.set(target, key, val, receiver)
            console.log('set', key, val)
            // console.log('result', result) // true
            return result // 是否设置成功
        },
        deleteProperty(target, key) {
            const result = Reflect.deleteProperty(target, key)
            console.log('delete property', key)
            // console.log('result', result) // true
            return result // 是否删除成功
        },
    }

    // 生成代理对象
    const observed = new Proxy(target, proxyConf)
    return observed
}

// 测试数据
const data = {
    name: 'zhangsan',
    age: 20,
    info: {
        city: 'beijing',
        a: {
            b: {
                c: {
                    d: {
                        e: 100,
                    },
                },
            },
        },
    },
}

//对数组的更改(如下标)也可以监听到
const data = ['1', '2', '3', '4']
const proxyData = reactive(data)
console.log(proxyData) //['1', '2', '3', '4']
proxyData[2] = 'test'
console.log(proxyData) //['1', '2', 'test', '4']

总结

  • 深度监听. 性能更好

  • 可监听新增/删除 属性

  • 可监听数组变化

  • 但是 Proxy 无法兼容所有的浏览器, 无法polyifll

vue3 中文文档

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值