vue3 和 vue2 响应式 原理及区别

90 阅读2分钟

vue3 的一些周边知识、 以及和vue2的一些对比

先导:先讲一些前置知识,比如proxy啊、比如ts的一些相关介绍。再讲vue3的一些设计理念,一些源码实现。最后再去结合前面这些知识,去看vue3的架构理念和设计理念。

我们知道vue是基于数据驱动的,也就是说vue的核心理念是数据驱动

驱动是什么。数据变化的时候,可以快速地反映出视图的变化,也就是数据去驱动视图。数据驱动的最重要的一点,就是对数据进行可变化的一个侦测。

那么vue2是如何实现对数据的驱动的呢?Object.defineProperty

Object.defineProperty 这个API是通过对数据的拦截来实现的。

接下来我们看一下,当数据变化时,这个api是如何进行拦截到变化。

第一步就是,对一个最基础的一个属性和对象进行拦截。

基本使用

1、要添加属性的对象
2、要定义或修改的属性的名称或[Symbol]
3、要定义或修改的属性描述符

Object.defineProperty(obj, prop, descriptor)

三个参数(对象,对象上面我们要监控的一个属性名,自定义的描述)

下面是例子,对一个对象属性的一个侦测

let person = {}
let personName = 'John'

Object.defineProperty(person, 'personName', {
    // 默认是不可枚举的(for in 打印不出来), 可: enumerable: true
    // 默认是不可修改的, 可: writeable: true
    // 默认不可删除, 可: configurable: true
    
    get: function () {
        console.log('触发了get方法')
        return personName
    },
    set: function (val) {
        console.log('触发了set方法')
        personName = val
    }
})

// 当读取person对象的personName属性时,触发get方法
console.log(person.personName)

// 对person.personName进行修改,触发set方法
person.personName = 'Jack'
console.log(person.personName)

// 不会打印任何信息 如需可枚举 上面代码enumerable: true加上就可以了
for (let key in person) {
    console.log(key)
}

当进行person上面的personName进行修改的时候,要去侦测到-获取了和设置了各自的动作。当获取的时候,需要进行依赖收集;当设置的时候,需要做dom渲染。vue这两个过程是比较复杂的,这里简化去说一下。

通过mdn文档我们知道,默认情况下,Object.defineProperty() 默认是不可枚举默认是不可修改默认不可删除。

上面说的是单属性的监听

那么接下来就是多属性对象的监听。Object.keys()进行遍历

let person = {
    name: '',
    age: 0
}

// 实现一个响应式函数
function defineProperty (obj, key, val) {
    Object.defineProperty(obj, key, {
        get () {
            console.log(`访问了${key}属性`)
            return val
        },
        set (newVal) {
            console.log(`${key}属性`)
        }
    })
}

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 4 天 点击查看活动详情