手写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. 需要遍历循环对象的所有属性。
相关推荐
yume_sibai1 小时前
大屏数据可视化 - 边框红绿呼吸灯实现详解
前端·信息可视化·typescript
竹林8181 小时前
从 ethers.js 迁移到 Viem:一个签名验证 Bug 让我彻底放弃旧爱
javascript
Hyyy1 小时前
很多Desktop都在上的Computer Use是什么
前端·llm
慢功夫1 小时前
开篇:VS Code 为什么不是一个普通 React App
前端·visual studio code
你挚爱的强哥1 小时前
Vue2 实现 1.5s 十连击监听(连续点击若干次),封装通用可复用点击检测工具,不用 data!Vue 封装通用连击监听方法,支持自定义时长与点击次数
前端·javascript·vue.js
半个落月2 小时前
用 LangChain.js 手写一个能读写文件和执行命令的 Mini Cursor
javascript·人工智能·后端
天外天-亮2 小时前
HBuilder X 使用 uview-plus 方式
开发语言·javascript·hbuilder x·uview-plus
huashengzsj2 小时前
Shopify个人建站如何搭建独立站:从零开始的完整指南
前端·网络·人工智能
程序猿小泓2 小时前
从 Claude Code 学 Agent Harness:一个前端工程师的 AI Agent 学习笔记
前端·人工智能·学习
柒和远方3 小时前
从审计日志到可下载证据包:事务型 Outbox、租约 fencing 与保留水位
前端·后端·架构