浅谈vue2和vue3之间的响应式原理
既然vue2和vue3都是基于vue的,为什么底层会一直改变,原本不想学习vue3的,觉得够用就行,但是有时候在vue2的项目中却会发现一种难以言语的不便
比如你不可能直接的去修改或者删除某个对象的属性或者值,尽管你可以通过set方法去修改,但是为什么不能修改呢,本质是数据虽然修改了但是页面还是呈现不出来呢?
~所以,前端搬运工还是要往前继续走,继续踩
模拟vue2的响应式原理
回顾一下Object.defineProperty()这是啥,我们去MDN走一趟----
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty
得到的解释是 ----
Object.defineProperty() 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。
语法----
Object.defineProperty(obj, prop, descriptor)
传值---
configurable- 当且仅当该属性的
configurable键值为true时,该属性的描述符才能够被改变,同时该属性也能从对应的对象上被删除。
默认为false。 enumerable- 当且仅当该属性的
enumerable键值为true时,该属性才会出现在对象的枚举属性中。
默认为false。
数据描述符还具有以下可选键值:
value- 该属性对应的值。可以是任何有效的 JavaScript 值(数值,对象,函数等)。
默认为undefined。 writable- 当且仅当该属性的
writable键值为true时,属性的值,也就是上面的value,才能被赋值运算符(en-US)改变。
默认为false。
存取描述符还具有以下可选键值:
get- 属性的 getter 函数,如果没有 getter,则为
undefined。当访问该属性时,会调用此函数。执行时不传入任何参数,但是会传入this对象(由于继承关系,这里的this并不一定是定义该属性的对象)。该函数的返回值会被用作属性的值。
默认为undefined。 set- 属性的 setter 函数,如果没有 setter,则为
undefined。当属性值被修改时,会调用此函数。该方法接受一个参数(也就是被赋予的新值),会传入赋值时的this对象。
默认为undefined。
通过下面的案例想想vue2的响应式原理以及数据劫持是如何的,顺便再想想vue.js的的设计模式--发布者-订阅者,可以去玩一下pubsub.js 这里只是浅谈一下响应式原理
//初数据
let person = {
name:'张大标',
age:90
}
let p = {}
Object.defineProperty(p,'name',{
configurable:true,
get(){
return person.name
},
set(value){
person.name = value
}
})
Object.defineProperty(p,'age',{
get(){
return person.age
},
set(value){
person.age = value
}
})
模拟vue3的响应式原理
我们先了解一下Proxy --- 代理
定义---
Proxy 对象用于创建一个对象的代理,从而实现基本操作的拦截和自定义(如属性查找、赋值、枚举、函数调用等)。
参数---
target- 要使用
Proxy包装的目标对象(可以是任何类型的对象,包括原生数组,函数,甚至另一个代理)。 handler- 一个通常以函数作为属性的对象,各属性中的函数分别定义了在执行各种操作时代理
p的行为。
那么p如何去映射person呢?那是不是直接联想到数据劫持?
const p = new Proxy(person,{
get(target,property){
return Reflect.get(target,property)
},
set(target,property,value){
Reflect.set(target,property,value)
},
deleteProperty(target,property){ //最关键的是这里,捕获数据的改变做响应式
return Reflect.deleteProperty(target,property) // 如果这里不明白,接着看.......--->>>>
}
})
再来引入下为什么要用Reflect --- 映射
Reflect 是一个内置的对象,它提供拦截 JavaScript 操作的方法。这些方法与proxy handlers (en-US)的方法相同。Reflect不是一个函数对象,因此它是不可构造的。
一个简单的reflect的例子-----
读操作----

写操作---

删除操作---

似乎你会觉得操作对象不需要用到reflect,但是reflec正在被ECMA在Object的大量API移植到其身上,如下文档----->
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Reflect

-----结束

浙公网安备 33010602011771号