手写vue响应式

一、vue2的Object.defineProperty()

javascript 复制代码
        let data = {   //相当于vue中的data
            msg: "",
            name: '',
            age: 222,
            adress: {
                country: 'China',
                province: 'Beijing'
            }
        }

        let vm = {} //相当于vue实例

        function observe(target) {
            if (typeof target !== 'object' || target === null) { return target }
            Object.keys(target).forEach(key => {

                defineReactive(target, key, target[key])
            })
        }
        //把data中的所有对象都变为响应式。

        function defineReactive(target, key, val) {
            //通过递归的方式把嵌套对象的属性设置为响应式。
            observe(val)
            Object.defineProperty(target, key, {
                get() {
                    // 在这里添加观察者对象 Dep.target 表示观察者
                    console.log('触发getter')
                    return val;
                },
                set(newVal) {
                    //处理data中对象新增属性无法监测的问题
                    observe(newVal)
                    //如果值不变则直接返回
                    console.log('触发setter,值为:' + newVal)
                    if (val !== newVal) {
                        val = newVal;
                        // 触发通知 更新视图
                        document.querySelector('.app').textContent = val
                    }
                }
            })
        }

        observe(data)
       // data.age = '333'
        data.name= { num: '222' }
        data.name.num = '333'

二、vue3的proxy

Proxy监听的是一个对象,对这个对象上的所有操作都会被监测到,这就可以代理所有属性了。

javascript 复制代码
   let data = {
            id: 22,
            name: "henry",
            address: {
                country: 'China',
                city: 'Beijing'
            }
        }
        let arr = [2, 33, 10, 93, 8, 22]
        //proxy 相对于Object.defineProperty,不用遍历对象的所有属性,它可以直接监听对象的所有属性。

        function observe(target) {
            return new Proxy(target, {
                           get(target, prop, receiver) {
                    console.log('触发了get,key为:' + prop)
                    return Reflect.get(...arguments)
                },
                set(target, key, newVal, receiver) {
                    console.log('触发了set,值为:' + newVal)
                    return Reflect.set(...arguments)
                }
            })

        }


        let proxyObj = observe(data)
        console.log(data.name)  // 触发了get,key为name
        proxyObj.name={firstName:'tom'}  // 触发了set,值为:[object Object]
        proxyObj.sex = 'male'// 触发了set,值为:male   
        let proxyArr = observe(arr)
        proxyObj.push(909)   //proxy 解决了vue2 响应式中,修改数组监测不到的问题。

        //proxy 解决了 Object.defineProperty 的几个问题
        //1、监测不到对象深度属性改变。(vue2中通过递归实现)
        //2、无法监测对对象新增属性的动作。(vue2中通过递归实现)
        //3、数组的push、pop等方法无法正确监测。(vue2中通过重写数组方法,在方法中进行递归)    
        //4、需要遍历循环对象的所有属性。

总结:

vue3 通过proxy处理响应式 解决了vue2中使用 Object.defineProperty 的几个问题

  1. 监测不到对象深度属性改变。(vue2中通过递归实现)
  2. 无法监测对对象新增属性的动作。(vue2中通过递归实现)
  3. 数组的push、pop等方法无法正确监测。(vue2中通过重写数组方法,在方法中进行递归)
  4. 需要遍历循环对象的所有属性。
相关推荐
C_V_Better14 分钟前
浏览器缓存机制:JavaScript 文件缓存导致 404 错误的解决方案
开发语言·前端·javascript·缓存
小救星小杜、17 分钟前
a = b &&c 的含义
开发语言·前端·javascript
uhakadotcom18 分钟前
Babylon.js:轻松打造Web 3D体验
前端·javascript·面试
parade岁月20 分钟前
告别代码质量隐患:Husky 生态工具链在前端工程化中的实战应用
前端·javascript
小成C20 分钟前
为什么会演化出RSC,SSR和RSC关系大解密
前端·react.js
过期的H2O222 分钟前
【H2O2 | 软件开发】Axios发送Http请求
前端·http·axios·交互
bug总结27 分钟前
vue3 public下引入图片路径打包后线上不显示问题解决
前端·javascript·vue.js
悠然青年帅30 分钟前
基于Vue+Canvas实现的画板绘画以及保存功能
前端
screct_demo33 分钟前
详细讲一下 Webpack 主要生命周期钩子流程(重难点)
前端·webpack·node.js
小妖66634 分钟前
vue2的webpack(vue.config.js) 怎么使用请求转发 devServer.proxy
javascript·vue.js·webpack