剑指Vue3深入浅出一文彻底弄懂Vue3响应式原理(proxy,Reflect)

更新时间:2023-07-25 11:44:06 阅读: 评论:0

剑指Vue3深⼊浅出⼀⽂彻底弄懂Vue3响应式原理
(proxy,Reflect)
什么是响应式?
⽬录
let m = 3
console.log(m);
console.log(m +'1aaaaaa');
console.log('hello');
当m的值发⽣变化的时候,我希望下⾯的三⾏代码都⾃动重新执⾏⼀遍。
// obj
const obj = {
name:'Sherry',
age:18
}
console.log('hello');
console.log('i love u ');
console.log(obj.name);
需求:当name的值发⽣改变的时候,底下三⾏代码重新执⾏,我们先想到封装⼀个函数
函数封装
const obj = {
name:'Sherry',
age:18
开心假日
}
//
let reactiveFn = []
function watchFn(fn){
reactiveFn.push(fn)
}
watchFn(function(){
console.log('hello')
console.log('i love u ')
console.log(obj.name)
}
)
obj.name = 'Lily'
巴尔扎克的作品reactiveFn.forEach(fn =>{
fn()
})
数组存放我们要执⾏的函数,我们要值改变时执⾏什么函数就把函数放进watchFn⾥⾯,watchFn会把函数push进来,最后forEach调⽤,但是现在这个数组收集的是name发⽣改变的时候所有需要执⾏的函数,如果是age,就不⾏,换⼀个对象,也不⽅便,那我们不⽤数组
类封装
class Depend{
constructor(){
}
4月开什么花addDepend(reactiveFn){
}
}
// obj
const obj = {
name:'Sherry',
age:18
}
const depend = new Depend()
function watchFn(fn){
depend.addDepend(fn)
}
watchFn(function(){
console.log('hello')
console.log('i love u ')
console.log(obj.name)
}
)
obj.name = 'Lily'
reactiveFn.forEach(fn =>{
fn()
})
那么此时,把数组和添加进数组的⽅法封装进类⾥之后,age和name就会分开来,每⼀个属性都会有对应的数组,现在可以⼀个属性对应⼀个dep对象
那现在,总不能⼀个属性改了,每次都forEach⼀下再执⾏吧,我们在类⾥再放⼀个⽅法
notify(){
fn()
})
}
这样响应的时候就调⽤notify
监听对象变化
现在还没有做到,我们应该是在我们更改对象的属性值之后,让它⾃⼰执⾏,⽽不是现在这样我们⾃⼰⼿动调⽤函数让它执⾏,现在我们应该来监听对象属性的变化了
两种⽅式:Proxy(vue3),Object.defineProperty(vue2),我们讲Proxy
const obj = {
name:'Sherry',
age:18
}
// 监听obj的变化
const objProxy = new Proxy(obj,{
get:function(target,key,receiver){
(target,key,receiver)
直板反手
},
t:function(target,key,newValue,receiver){
Reflect.t(target,key,newValue,receiver)
// 我们希望⾃动监听
}
})
function watchFn(fn){
depend.addDepend(fn)
}
const depend = new Depend()
watchFn(function(){
console.log('hello')
console.log('i love u ')
8888console.log(objProxy.name)
}
)
objProxy.name = 'Lily'
objProxy.name = 'Lily'
objProxy.name = 'Lily'
现在这样,每当我们更改name的时候,Proxy会⾃动替我们监听并且执⾏notify
但是,如果age改变
const depend = new Depend()
watchFn(function(){
console.log('hello')
console.log('i love u ')
console.log(objProxy.name)
}
)
watchFn(function(){
console.log(objProxy.age,'age is change111');
})
watchFn(function(){
console.log(objProxy.age,'age is change22');
})
objProxy.age = 100
当age发⽣改变时,所有watchFn⾥⾯的函数都会⾃⼰执⾏⼀遍
现在这样的设计,由于t函数⾥⾯的depend收集的是所有属性的依赖,所有不管哪个属性发⽣变化时,所有函数都会重新执⾏,这样不可以,我们要做⼀个区分
你是最美的风景// 封装⼀个获取depend的函数
const targetMap = new WeakMap()
function getDepend(target,key){
// 根据target获取对象
let map = (target)
// 新建map
if(!map){
map = new Map()
targetMap.t(target, map)
}新的旅程
// 根据key获取depend
let depend = (key)
if(!depend){
守法公民depend = new Depend()
map.t(key,depend)
}
return depend
}
// obj的响应式
const obj = {
name: 'Sherry',
age: 18
}
// 监听obj的变化
const objProxy = new Proxy(obj, {
get: function (target, key, receiver) {
(target, key, receiver)
},
t: function (target, key, newValue, receiver) {
Reflect.t(target, key, newValue, receiver)
// 我们希望⾃动监听
// ify()
// 获取到最真实的depend,name/age
const depend = getDepend(target,key)
}
})
⼤家浅看⼀下关系图,这个图能很好理解封装的函数getDepend,⾄于为什么是map,map和对象的
区别就在于,map的键名可以是任何值,对象也可以,但是对象不⾏,对象的键名不能是对象,如果是对象的话,会⾃动转成字符串,⼤家有兴趣可以测试⼀下

本文发布于:2023-07-25 11:44:06,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/fanwen/fan/82/1116350.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:函数   对象   属性   封装   监听   数组   变化
相关文章
留言与评论(共有 0 条评论)
   
验证码:
推荐文章
排行榜
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图