Vue2.x和3.x的响应式原理

202 阅读1分钟

vue2.x 数据响应式核心原理

官网描述:当你把一个普通的 JavaScript 对象传入 Vue 实例作为 data 选项,Vue 将遍历此对象所有的 property,并使用 Object.defineProperty 把这些 property 全部转为 getter/setterObject.defineProperty 是 ES5 中一个无法 shim 的特性,这也就是 Vue 不支持 IE8 以及更低版本浏览器的原因。

实现对一个属性进行监听转换

<script>
        // 模拟vue中的data
        let data = {
            msg:'xuke'
        }
        // 模拟vue的 实例
        let vm = {}

        // 数据劫持:当我们访问或者设置 vm 中的成员的时候,做一些干预的操作
        Object.defineProperty(vm,'msg',{ // 第一参数为对象,第二个参数为对象中的属性,第三个参数为属性描述符,我们可以为msg设置get和set方法
            // 可枚举可遍历
            enumerable:true,
            // 可配置,可以使用delete删除,可通过 defineprototype重新定义
            configurable:true,

            // 当获取值时执行的方法
            get(){
                console.log("获取我了")
                return data.msg
            },
            // 当设置值时执行的方法
            set(newVable){
                console.log("设置我了")
                if(data.msg === newVable){
                    return
                }
                data.msg = newVable
                // 更新dom
                document.querySelector("#app").textContent = data.msg
            }
        })

        // 测试
        vm.msg = 'xuke haha'
        console.log(vm.msg)
    </script>

实现对多个属性的监听

思路:我们将数据劫持监听封装成一个函数,函数中我们遍历data中得每个属性,并使用循环的方式给每个属性加监听劫持

 <script>
        // 模拟vue中的data
        let data = {
            msg: 'xuke',
            count: 10
        }
        // 模拟vue的 实例
        let vm = {}
        proxyData(data)
        // 将监听的属性封装成一个函数
        function proxyData(data) {
            Object.keys(data).forEach(key => {
                // 数据劫持:当我们访问或者设置 vm 中的成员的时候,做一些干预的操作
                Object.defineProperty(vm, key, { // 第一参数为对象,第二个参数为对象中的属性,第三个参数为属性描述符,我们可以为msg设置get和set方法
                    // 可枚举可遍历
                    enumerable: true,
                    // 可配置,可以使用delete删除,可通过 defineprototype重新定义
                    configurable: true,
                    // 当获取值时执行的方法
                    get() {
                        console.log("获取我了")
                        return data[key]
                    },
                    // 当设置值时执行的方法
                    set(newVable) {
                        console.log("设置我了")
                        if (data[key] === newVable) {
                            return
                        }
                        data[key] = newVable
                        // 更新dom
                        document.querySelector("#app").textContent = data[key]
                    }
                })
            })
        }
        // 测试
        vm.msg = 'xuke haha'
        console.log(vm.msg)
    </script>

Vue3.x 数据响应原理

区别2.x:

  1. 直接监听对象 而非属性
  2. ES6中新增,IE不支持,性能由浏览器优化
  3. 通过ES6新增Proxy进行数据监听
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <div id="app">
        xuke
    </div>
    <script>
        // 模拟vue中的data
        let data = {
            msg: 'xuke',
            count: 10
        }
        // 模拟vue的 实例
        let vm = new Proxy(data,{
            // 执行代理行为的函数

            // 当访问vm的成员会执行
            get(target,key){
                console.log("执行get了")
                return target[key]
            },

            // 当设置vm的成员会执行
            set(target,key,newValue){
                console.log("设置set了")
                if(target[key]===newValue){
                    return
                }
                target[key]=newValue
                document.querySelector("#app").textContent = target[key]
            }
        })
      
        // 测试
        vm.msg = 'xuke haha'
        console.log(vm.msg)
    </script>

</body>

</html>