Proxy(vue响应式原理:数据侦测--数据劫持和数据代理)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Proxy(vue响应式原理:数据侦测--数据劫持和数据代理)相关的知识,希望对你有一定的参考价值。

参考技术A Object.defineProperty : 通过设定对象属性getter/setter方法来监听数据的变化,同时getter也用于依赖收集,而setter在数据变更时通知订阅者更新视图。

1.无法检测到对象属性的新增或删除
由于js的动态性,可以为对象追加新的属性或者删除其中某个属性,这点对经过Object.defineProperty方法建立的响应式对象来说,只能追踪对象已有数据是否被修改,无法追踪新增属性和删除属性,这就需要另外处理。

2.不能监听数组的变化
vue在实现数组的响应式时,它使用了一些hack,把无法监听数组的情况通过重写数组的部分方法来实现响应式,这也只限制在数组的push/pop/shift/unshift/splice/sort/reverse七个方法,其他数组方法及数组的使用则无法检测到。

Proxy,字面意思是代理,是ES6提供的一个新的API,用于修改某些操作的默认行为,可以理解为在目标对象之前做一层拦截,外部所有的访问都必须通过这层拦截,通过这层拦截可以做很多事情,比如对数据进行过滤、修改或者收集信息之类。借用 proxy的巧用 的一幅图,它很形象的表达了Proxy的作用。

ES6原生提供的Proxy构造函数,用法如下:

其中obj为Proxy要拦截的对象,handler用来定制拦截的操作,返回一个新的代理对象proxy;Proxy代理特点:
1.Proxy的代理针对的是整个对象,而不是像Object.defineProperty针对某个属性。只需做一层代理就可以监听同级结构下的所有属性变化,包括新增属性和删除属性

2.Proxy也可以监听数组的变化

参考: https://juejin.cn/post/6850418111985352711

敲黑板,划重点!!!Vue3.0响应式实现原理 —— proxy()

Vue3.0响应式实现原理


1. 先来回顾一下Vue2.0的响应式原理

  • 通过 Object.defineProperty() 实现数据劫持

存在的问题

  • 针对对象:新增属性,删除属性,界面不更新
  • 针对数组:通过下标修改数组,界面不会自动更新
<!DOCTYPE html>
<html>
    <head>
        <title>模拟vue2.0</title>
    </head>
    <body>
        <input type="text" id="username">
        <br>
        显示值:<span id="uName"></span>
        <script>
        var obj = ;
        // 模拟双向数据绑定
        //Object.defineProperty(obj, prop, descriptor)
        //直接在一个对象上定义一个新属性,或者修改一个对象的现有属性, 并返回这个对象。
        //obj 要在其上定义属性的对象。
        //prop 要定义或修改的属性的名称。
        //descriptor 将被定义或修改的属性描述符。
        Object.defineProperty(obj,"username",
          // Value:"Jack",
          get:function()
            console.log("取值");
          ,
          set:function(val)
            console.log("设置值");
            document.getElementById("uName").innerText=val;
          
        );
        document.getElementById("username").addEventListener("keyup",function()
          obj.username= event.target.value;
        )
        //在控制台中输入obj.username会自动触发get方法,输入obj.username="aaa"会自动触发set方法
        //此时并没有用事件进行监听,所以修改监听事件里的代码
        </script>
      </body>
</html>

2. Vue3.0原理实现 —— Proxy()

  • 引用数据类型的增删改查统统在行,非常强大
<!DOCTYPE html>
<html>
    <head>
        <title>vue3响应式</title>
    </head>
    <body>
        <script>
            // type="text/javascript"
            let obj = 
                name: '小明',
                age: 18
            
            // 1. window内置的
            // window.Proxy() => 代理
            // obj为源数据
            const p = new Proxy(obj, 
                // 这里虽然也是get set 但是要比Object.defin()要聪明一些
                get(target, propName)
                    // target 源数据  // b具体属性
                    // console.log("读取P的属性")   // a, b
                    console.log(`读取P的$propName属性`)
                    // return target[propName]
                    return Reflect.get(target, propName)
                ,

                // 修改+新增都可以捕获
                set(target, propName, value)
                    // console.log("修改了P的属性")
                    console.log(`修改了P的$propName属性,值为$value`)
                    // 写到这里 还不是响应式 要去修改obj的值
                    // target[propName] = value
                    return Reflect.set(target, propName, value)
                ,
                // 加一个删除
                deleteProperty(target, propName)
                    console.log(`删除了P的$propName属性`)
                    // return delete target[propName]
                    return Reflect.deleteProperty(target, propName)
                ,
            )
        </script>
      </body>
</html>

3. 重点说明 —— Reflect

3.1 Reflect 是用来做什么的?

  • 动态对被代理对象的相应属性进行特定的操作(ES6新增)
  • 看到上面的代码,你会发现每行Reflect代码上面都注释了一行,实际上不用它,用它上面的代码也可以实现响应式
  • 但是Vue3.0 却用的是 Reflect,还是有些深意的

3.2 为什么要用Reflect ?

  • 大家可以自行百度,我这里简单说一下(放链接我怕文章发不出去,深感抱歉)

  • 简单来说,主要是为了减少源码中的 try catch,如果不使用 Reflect,整个框架需要有大量的 try catch,才能保证在出错的情况下顺利运行,但是源码就会不好维护,看起来不雅观

  • 使用Reflect,即使代码出错,可以在抛出错误的同时,让代码正常运行,保证框架的健壮性!

1. 希望本文能对大家有所帮助,如有错误,敬请指出

2. 原创不易,还请各位客官动动发财的小手支持一波(关注、评论、点赞、收藏)
3. 拜谢各位!后续将继续奉献优质好文
4. 如果存在疑问,可以私信我

以上是关于Proxy(vue响应式原理:数据侦测--数据劫持和数据代理)的主要内容,如果未能解决你的问题,请参考以下文章

敲黑板,划重点!!!Vue3.0响应式实现原理 —— proxy()

敲黑板,划重点!!!Vue3.0响应式实现原理 —— proxy()

敲黑板,划重点!!!Vue3.0响应式实现原理 —— proxy()

能说说vue的响应式原理吗?

vue 响应式原理

《深入浅出Vue.js》读书笔记2-Proxy的自我尝试