手写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. 需要遍历循环对象的所有属性。
相关推荐
郭老二5 小时前
【前端】vue3:编译步骤
前端
不在逃避q5 小时前
Trae/Vs Code/Cursor命令行无法跑npm命令
前端·arcgis·npm
夏殇之殁6 小时前
包中创建自定义列表项。 . 使用自定义列表项进行数据绑定 . 将天气预报数据保存到本地内存表,通过LiveBindings进行显示。 ...
服务器·前端·javascript
The Chosen One9856 小时前
高进度算法模板速记(待完善)
java·前端·算法
陈随易6 小时前
MoonBit抓包模块pcap,查看电脑的每一次联网通信
前端·后端·程序员
新中地GIS开发老师7 小时前
WebGIS开发学生作品|低空航天管理与航线规划系统
前端·javascript·webgis·三维gis开发
用户059540174467 小时前
大模型对话记忆持久化踩坑实录:用 Playwright 自动化测了 300 次,终于揪出会话丢失的真凶
前端·css
丙氨酸長鏈7 小时前
Web前端入门第 问:JavaScript 一个简单的 IndexedDB 数据库入门示例
前端·javascript·数据库
kyriewen8 小时前
面试官让我手写虚拟列表——AI生成的版本,快速滚动几下就白屏了
前端·javascript·面试
IT_陈寒8 小时前
Vite热更新失效?你可能漏了这个配置
前端·人工智能·后端