手写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工程师11 分钟前
迭代器实现简单演示:斐波拉契取值
前端
simple丶12 分钟前
Elpis 服务端引擎
前端
黄天才丶12 分钟前
高级前端篇-性能优化(这一篇就够了!w字长文,持续更新中)
前端
章鱼小丸子逃跑中15 分钟前
若依RuoYi-Cloud-Plus微服务版(完整版)前后端部署
java·前端·后端·微服务
qipao17 分钟前
马拉车算法Kimi详解(js版)
前端·算法
小彭SG18 分钟前
5年前端机缘巧合做起鸿蒙开发,你也要来吗?
前端·harmonyos
~废弃回忆 �༄23 分钟前
CSS中绝对定位
前端·css·css中绝对定位
best66635 分钟前
Monorepo 全解析:概念、价值、选择与实践(Vue3方式)
前端·架构
Eliauk__39 分钟前
Vue 事件绑定深入解析:@click="func" vs @click="func()"
前端·vue.js·面试
用户21411832636021 小时前
dify案例分享-deepseek赋能从 Excel 表格到统计图,一键生成代码不是梦
前端