分类
默认

Vue 3 用 Proxy 实现响应式

Proxy 实现响应式

  • 深度监听,性能更好
  • 可监听 新增/删除属性
  • 可监听数组变化
  • 但,无法兼容所有浏览器,无法 polyfill
// 创建响应式
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 result // 返回结果
            // 深度监听,把上面修改成下面
            return reactive(result);
            // 那么性能是如何提升?
            /**
             *  Object.defineProperty 一次性递归完
             *  Proxy 是 get 到哪一层,就递归到哪一层
             */
        },
        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)
            return result // 是否设置成功
        },
        deleteProperty(target, key) {
            const result = Reflect.deleteProperty(target, key)
            console.log('delete property', key)
            console.log('result', result)
            return result // 是否删除成功
        }
    }
    // 生成代理对象
    const observed = new Proxy(target, proxyConf)
    return observed
}
// 测试数据
const data = {
    name: 'zhangsan',
    age: 20,
    info: {
        city: 'shenzhen',
        a: {
            b: {
                c: {
                    d: {
                        e: 100
                    }
                }
            }
        }
    }
}
const proxyData = reactive(data);
// 测试
console.log(proxyData.age)
// get age
// 20
// 没有深度监听
console.log(proxyData.info.city)
// get info
// shenzhen
// 深度监听
console.log(proxyData.info.city)
// get info
// get city
// shenzhen
// 新增的 key
console.log(proxyData.age1=100)
// 新增的 key age1
// set age1 100
// result true
// 100

那么性能是如何提升?

  • Object.defineProperty 一次性递归完
  • Proxy 是 get 到哪一层,就递归到哪一层