vue2 VS vue3 数据双向绑定

vue2 数据双向绑定

实现方法
  • Object.definedProperty()进行数据劫持
  • 结合发布订阅方式
由ES5提供 Object.defineProperty 缺点
  1. 只能劫持对象的属性, 初始化时,需要对每个对象每个属性进行遍历,如果属性值还是对象,则还需要深度遍历;即使没有使用这个属性,也会将该属性进行响应式处理,性能不高;
  2. 只能监听到对象属性已有数据是否被修改;无法监听到对象属性的新增和删除;
  3. 无法监听到数组的变化,例如,利用数组下标添加数据时,无法实施响应。
  4. 其在实现数组响应式时,使用了一些hack(触发视图更新),把无法监听数组的情况通过重写数组来实现响应,也仅限于数组的pop,push,shift,unshift,splice,sort,reverse七个方法,其他方法无法检测到。

vue3 数据双向绑定

实现方法
  • Proxy代理,使用ref 或者reactive 将数据转化为响应式数据
proxy 优点
  1. 可以劫持整个对象,而非对象属性,并返回一个新的对象;
  2. 代理对象可以劫持对象属性的访问、新增、删除等操作,不需要初始化时遍历所有属性;
  3. 如果有多层属性嵌套,只有在访问到某个属性的时候才会递归处理下一级属性;
  4. 可以监听到数组变化,例如索引,length…
  5. 不仅可以代理对象,还可以代理数组,还可以代理动态增加的属性。
缺点
  • 存在兼容性问题,不能用polyfill来兼容
  • polyfill主要抚平不同浏览器之间对Js实现的差异
实现案例
  • 实例引用于:https://blog.csdn.net/weixin_44700978/article/details/118769759
const toProxy = new WeakMap(); // 存放的是代理后的对象
const toRaw = new WeakMap(); // 存放的是代理前的对象

function trigger() {
    console.log('触发视图更新')
}

function isObject(target) {
    return typeof target === 'object' && target !== null;
}

function reactive(target) {
    if (!isObject(target)) return target;
    
    const proxy = toProxy.get(target)
    
    // 如果代理表中已经存在了  就把这个结果返回
    if (proxy) return proxy
    
    // 如果这个对象已经被代理过了  就直接返回
    if (toRaw.has(target)) return target;
    
    const handlers = {
        set(target, key, value, receiver) {
            if (target.hasOwnProperty(key)) {
                trigger()
            }
            return Reflect.set(target, key, value, receiver)
        },
        get(target, key, value, receiver) {
            const res = Reflect.get(target, key, receiver)
            if (isObject(target[key])) {
                return reactive(res)
            }
            return res;
        },
        deleteProperty(target, key) {
            return Reflect.deleteProperty(target, key)
        }
    }
    const observed = new Proxy(target, handlers)
    toProxy.set(target, observed);
    toRaw.set(observed, target)
    return observed
}
    const obj = {
        name: 'xxx',
        arr: [1, 2, 3]
    }

    let p = reactive(obj)
    p = reactive(p)
    p = reactive(p)
    p.arr.push(4)
    console.log(p)  //触发视图更新 { name: 'xxx', arr: [ 1, 2, 3, 4 ] }

Reflect解析地址:https://blog.csdn.net/qq_40963664/article/details/118788697

  • Reflect是ES6为操作对象而提供的新API,proxy对象的方法在Reflect上都能找到;
  • new WeakMap() 是弱引用,在内存不足的时候垃圾回收机制才会回收,可以作为缓存。
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值