vue的响应式原理
响应式
vue2响应式原理就是通过object.defineProperty来劫持对象上的get和set方法,通过对象上的复杂数据类型递归的方式实现复杂数据劫持,然后通过发布订阅者模式来通知前端视图层更新,从而实现响应式(他还只会监听原有的数据和对象)。
vue3的响应式相对于vue2是比较简单的,它是直接通过proxy代理来监听对象的get和set值,然后返回一个proxy对象,然后通过发布订阅者模式更新前端视图
自我总结
vue2相对于vue3来说实现的响应式更加消耗性能,vue3在底层中其实也使用到了递归,但是相对于vue2一开始就是便利对象然后进行判断处理是否为复杂数据类型,如是则会递归监听复杂数据类型。
而vue3是在获取数的时候进行判断获取值是否为复杂数据类型,如是则递归深度代理。
vue2监听(简洁版)
let obj = {
username : "小编泰裤了"
}
function monitor(target,key,value){ //定义函数进行监听
Object.defineProperty(target,key,{
get(){
return value
},
set(newVal){
if(newVal != value){
value = newVal
observer(newVal)
}
}
})
}
function observer(data){
if(typeof data !='object' || typeof data == null){//做判断来看你是否为复杂数据类型,是则递归便利
observer(data)
}
for (const key in data) {
monitor(data,key,data[key])
}
}
observer(obj)
console.log(obj);
vue3监听(简洁版)
<script>
let obj = {
username: "小编泰裤了"
}
let headle = {
get(target, key) {
let temp = target[key]
if(typeof temp == 'object'){
return monitor(temp)
}
return temp
},
set(target, key, value) {
target[key] = value
}
}
function monitor(data) {
return new Proxy(data, headle)
}
let user = monitor(obj)
console.log(user);
</script>
vue2数组监听
数组考虑到defineProperty的消耗,所以没有做监听,但是vue2对数组的【push,unshift,shift,prop,splice,sort,resver】(重写数组的方法)进行了重写的方式来对数组劫持
,同时也通知前端视图更新
缺点
不能监听数据的索引和长度的变化
底层代码实现
<script>
let obj = {
num: 12,
username: '小编太酷了',
gradeList: [1, 2, 3, 4, 5]
}
let newArrayProprotype = Object.create(Array.prototype);
let oldArrayProprotype = Array.prototype;
['push', 'sort', 'resver', 'unshift', 'shift', 'splice', 'pop'].forEach((mthd) => {
newArrayProprotype[mthd] = function (...ary) {
console.log("用户调用了数组方法中的:", mthd);
return oldArrayProprotype[mthd].call(this, ...ary)
}
})
function constest(target, key, value) {
observer(value)
Object.defineProperty(target, key, {
get() {
return value
},
set(newVal) {
if (value != newVal) {
value = newVal;
observer(newVal)
}
}
})
}
function observer(data) {
if (typeof data != "object" || typeof data == null) {
return
}
if (Array.isArray(data)) {
data.__proto__ = newArrayProprotype
} else {
for (const key in data) {
constest(data, key, data[key])
}
}
}
observer(obj)
obj.gradeList.push(6, 7, 8)
console.log(obj.gradeList);
</script>