vue2和vue3的代理区别———proxyES6新特性 (proxy拦截)

对象修改会触发对象的get set 方法,在方法内进行拦截,但是Proxy只能拦截到目标对象自身属性的变化,所以进行递归去遍历对象的对象再去拦截,去实现响应式

1. 首先可以先了解

vue2.0与vue3.0及vue与react的区别及说明

2.vue2.0 与 vue3.0的双向绑定原理

  • Vue2通过使用 Object.defineProperty 来劫持对象属性的 geter 和 seter 操作,当数据发生改变发出通知。
  • Vue3通过ES6的新特性proxy来劫持数据,当数据改变时发出通知。
  • Vue2无法检测精确数组对象变化。
  • vue3可以检测到对象/数组内部数据的变化,更精准的变更通知。
  • vue2使用 Vue.set 来给对象新增一个属性时,这个对象的所有watcher 都会重新运行;
  • vue3只有依赖那个属性的 watcher 才会重新运行 vue3默认进行懒观察。
  • vue2.0数据一开始就创建了观察者,数据很大的时候,就会出现问题 。
  • vue3中进行了优化只有用于渲染初始化可见部分的数据,才会创建观察者,效率更高 。

3.proxyES6新特性

原出处:手写组合api reactive和ref

大家都知道在vue3中响应式原理有原先的object.defineProperty换成了es6的新特性Proxy。

Proxy到底是什么

可以简单的理解为一个拦截器,他可以对任何对象的绝大部分行为和操作进行干涉,也就是我们常说的拦截。一提到拦截是不是就有感觉了。有了拦截不就可以实现响应式了嘛!也的确如此,对new Proxy返回的代理对象进行大部分操作如增删改读都可以被拦截到,我们就可以在其中做一些其他的事情。Proxy当然不止这些功能,他提供了多达13种行为的拦截,具体的可以自行查阅文档

- proxy和object.defineProperty的区别在哪儿?

我们都知道object.defineProperty只能拦截到对象自身以有的属性,而后续新增的属性是无法拦截到的,所以vue2提供了$set等一系列的api来帮助完善响应式。并且object.defineProperty并没有办法拦截到数组的一些变更,而vue2则采用了重写js种能修改源数据的数组api来实现数组的响应式,这些问题在proxy中都不存在了,这就是二者区别以及他的出现解决了vue2的哪些问题。

所以 对象修改会触发对象的get set 方法,在方法内进行拦截,但是Proxy只能拦截到目标对象自身属性的变化,所以进行递归去遍历对象的对象再去拦截,去实现响应式。

- vue3中的王牌响应式api reactive和ref

两个api都是包装数据用的,使数据变为响应式,唯一的不同点就是reactive用于包装对象和数组ref则可以用于包装各种类型。经过ref包装后的值需要通过.value的方式获取。其实ref在包装对象和数组类型的时候也是调用的reactive,具体的步骤看后续实现就行。

实现一个reactive
const reactiveHandler = {
    get(target,key){
        console.log('拦截到了读取数据',key)
        return Reflect.get(target,key)
    },
    set(target,key,val){
        console.log('拦截到了更新或新增数据',key)
        return Reflect.set(target,key,val)
    },
    deleteProperty(target,key){
        console.log('拦截到了删除数据',key)
        return Reflect.deleteProperty(target,key)
    }
}
function reactive(target) {
    if(target&&typeof target==='object'){
        if(Array.isArray(target)){
            target.forEach((d,index)=>{
                target[index] = reactive(d)
            })
        }else{
            Object.keys(target).forEach(d=>{
                target[d] = reactive(target[d])
            })
        }
        return new Proxy(target,reactiveHandler)
    }
    return target
}
实现一个ref(运用到对象自带的get 和set 方法)

get 和set可以指定一个属性名,当我们在访问这个属性名的时候就会触发get和set方法。就可以实现拦截的效果拉。

{
        _num:0,
        get num(){
            console.log('劫持到了get')
            return this._num
        },
        set num(val){
            console.log('劫持到了set',val)
            this._num= val
        }
    }
function ref(target) {
    return{
        _value:reactive(target),
        get value(){
            console.log('劫持到了get')
            return this._value
        },
        set value(val){
            console.log('劫持到了set',val)
            this._value = val
        }
    }
}
  • 10
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值