手写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. 需要遍历循环对象的所有属性。
相关推荐
breeze jiang10 分钟前
Next.js 16 App Router 实战:从 About、Blog 动态路由到全局 404
开发语言·javascript·ecmascript
小蒜学长15 分钟前
vue旅游攻略网站(代码+数据库+LW)
java·数据库·vue.js·spring boot·后端·旅游
IT_陈寒28 分钟前
Python装饰器把我坑惨了,原来这样用才不掉链子
前端·人工智能·后端
程序员爱钓鱼1 小时前
Rust Associated Type关联类型详解:为Trait定义内部类型
前端·后端·rust
zh_xuan1 小时前
个人主页左侧菜单支持分组,以及菜单显示和隐藏
前端·javascript·css
Ming_studying2 小时前
HTML + CSS + JavaScript实现可视化JSON工具:格式化、折叠、搜索与错误定位
javascript·css·html·json·数据可视化·web工具
Emily156853598705 小时前
Emerson 1C31129G03 Analog Input Module
java·开发语言·前端·plc·emerson·1c31129g03·input module
To_OC10 小时前
面试被问了三回三栏布局,这次我终于把 BFC 那层窗户纸捅破了
前端·css·面试
To_OC10 小时前
啃完 TS 工具类型我发现:Pick 和 Omit 原来就是一层窗户纸
前端·面试·typescript
风月说与山鬼11 小时前
三、大括号语法
前端·react.js