vue2的响应式原理
-
实现原理:
对象类型:通过Object.defineProperty() 对属性读取,修改进行拦截(数据劫持) 数组类型: 通过重写更新数组的一系列方法来实现拦截 ( 对数组的变更方法进行了包裹)
-
存在问题:
新增属性,删除属性,界面不会更新 直接通过下标修改数组,界面不会自动更新
-
在vue2 中解决的方法:
对象追加属性:
this.$set(对象,添加的属性,添加的值)
或者引入import Vue from 'vue'
Vue.set(对象,添加的属性,添加的值)
对象删除属性:
this.$delete(对象,属性名)
或者引入import Vue from 'vue'
Vue.delete(对象,添加的属性,添加的值)
数组修改元素:
this.$set(对象,数组下标,值)
this.数组.splice(起始位置,第几个元素,修改的名)
数组删除元素:
this.数组.splice(起始位置,0)
模拟vue2 中的响应式原理
Object.defineProperty
Object.defineProperty( obj , prop , descriptor )
obj : 要定义属性的对象。
prop : 要定义或修改的属性的名称或 Symbol 。
descriptor : 要定义或修改的属性描述符
let person={
name:'xwxw',
age:18
}
let p={}
for(let k in person){
Object.defineProperty(p,k,{
// 表示可以删除
configurable:true,
get(){
return person[k];
},
set(value){
person[k]=value;
}
})
}
vue3 响应式原理
-
实现原理
- 通过Proxy(代理): 拦截对象中的任意属性的变化,包括:属性值的读写,属性的添加,属性的删除等.
- 通过Reflect(反射): 对杯代理对象的属性进行操作
模拟vue3 响应式原理
反射机制
Reflect
是一个内建的对象,用来提供方法去拦截 JavaScript 的操作。
handler ⽅法 | 默认调⽤ | 功能 |
---|---|---|
get | Reflect.get() | 获取对象身上某个属性的值 |
set | Reflect.set() | 在对象上设置属性 |
has | Reflect.has() | 判断一个对象是否存在某个属性 |
deleteProperty | Reflect.deleteProperty() | 删除对象上的属性 |
getProperty | Reflect.getPrototypeOf() | 获取指定对象原型的函数 |
setProperty | Reflect.setPrototypeOf() | 设置或改变对象原型的函数 |
isExtensible | Reflect.isExtensible() | 判断一个对象是否可扩展 (即是否能够添加新的属性) |
preventExtensions | Reflect.preventExtensions() | 阻止新属性添加到对象 |
getOwnPropertyDescriptor | Reflect.getOwnPropertyDescriptor() | 获取给定属性的属性描述符 |
defineProperty | Reflect.defineProperty() | 定义或修改一个对象的属性 |
ownKeys | Reflect.ownKeys() | 返回由目标对象自身的属性键组成的数组 |
apply | Reflect.apply() | 对一个函数进行调用操作,同时可以传入一个数组作为调用参数 |
construct | Reflect.construct() | 对构造函数进行 new 操作,实现创建类的实例 |
.preventExtensions | Reflect.preventExtensions() | 阻止新属性添加到对象 |
代理对象
Proxy
是js中的原生对象,用来创建一个对象的代理,可以实现基本操作的拦截和自定义
new Proxy(target, handler)
-
target
是要代理的对象 -
handler
中定义了基本操作的逻辑
let person={
name:'xwxw',
age:18
}
const p= new Proxy(person,{
// target 表示的person对象, propName 代表的是读取的属性名
get(target,propName){
return Reflect.get(target,propName)
},
set(target,propName,value){
Reflect.set(target,propName,value)
},
deleteProperty(target,propName){
return Reflect.deleteProperty(target,propName)
}
})
vue3中 reactive对比ref
-
从定义数据的角度对比:
- ref用来定义:
基本数据类型
- reactlve用来定义:
对象(或数组)类型数据
- ref也可以用来定义
对象或数组数据类型
,他内部会自动通过reactive
转为代理对象
- ref用来定义:
-
从原理角度对比:
- ref通过
Object.defineProperty()
的get
和set
来实现响应式(数据劫持) - reactive通过使用
Proxy
来实现响应式(数据劫持),并通过Reflect
操作源对象
内部的数据
- ref通过
-
从使用角度对比:
- ref定义的数据:操作数据需要
.value
,读取数据时模板中不需要.value
- reactive定义的数据: 操作与读取数据都不需要
.value
- ref定义的数据:操作数据需要