Vue3的响应式原理是什么(vue3,开发技术)

时间:2024-05-03 21:22:53 作者 : 石家庄SEO 分类 : 开发技术
  • TAG :

接下来,请跟着小编一起来学习吧!

Proxy

Vue3 的响应式原理依赖了 Proxy 这个核心 API,通过 Proxy 可以劫持对象的某些操作。

constobj={a:1};
constp=newProxy(obj,{
get(target,property,receiver){
console.log("get");
returnReflect.get(target,property,receiver);
},
set(target,property,value,receiver){
console.log("set");
returnReflect.set(target,property,receiver);
},
has(target,prop){
console.log("has");
returnReflect.has(target,prop);
},
deleteProperty(target,prop){
console.log("deleteProperty");
returnReflect.deleteProperty(target,prop);
},
});

p.a;//输出-->get
p.a=2;//输出-->set
"a"inp;//输出-->has
deletep.a;//输出-->deleteProperty

如上例子,我们用 Proxy 代理了 Obj 对象的属性访问、属性赋值、in 操作符、delete 的操作,并进行 console.log 输出。

Reflect

Reflect 是与 Proxy 搭配使用的一个 API,当我们劫持了某些操作时,如果需要再把这些操作反射回去,那么就需要 Reflect 这个 API。

由于我们拦截了对象的操作,所以这些操作该有的功能都丧失了,例如,访问属性 p.a 应该得到 a 属性的值,但此时却不会有任何结果,如果我们还想拥有拦截之前的功能,那我们就需要用 Reflect 反射回去。

constobj={a:1};
constp=newProxy(obj,{
get(target,property,receiver){
console.log("get");
returnReflect.get(target,property,receiver);
},
set(target,property,value,receiver){
console.log("set");
returnReflect.set(target,property,receiver);
},
has(target,prop){
console.log("has");
returnReflect.has(target,prop);
},
deleteProperty(target,prop){
console.log("deleteProperty");
returnReflect.deleteProperty(target,prop);
},
});

举个例子

以下全文我们都会通过这个例子来讲述 Vue3 响应式的原理。

<divid="app"></div>

<script>
//创建一个响应式对象
conststate=reactive({counter:1});

//立即运行一个函数,当响应式对象的属性发生改变时重新执行。
effect(()=>{
document.querySelector("#app").innerHTML=state.counter;
});

//2s后视图更新
setTimeout(()=>{
state.counter+=1;
},2000);
</script>

我们用 reactive 创建了一个响应式对象 state,并调用了 effect 方法,该方法接受一个副作用函数,effect 的执行会立即调用副作用函数,并将 state.counter 赋值给 #app.innerHTML;两秒后,state.counter += 1,此时,effect 的副作用函数会重新执行,页面也会变成 2.

内部的执行过程大概如下图所示:

Vue3的响应式原理是什么

  • 调用 reactive() 返回一个 Proxy 代理对象,并劫持对象的 get 与 set 操作

  • 调用 effect() 方法时,会访问属性 state.counter,此时会触发 proxy 的 get 操作。

  • get 方法会调用 track() 进行依赖收集;建立一个对象(state)、属性(counter)、effect 副作用函数的依赖关系;

  • set 方法会调用 trigger() 进行依赖更新;通过对象(state)与属性(coutner)找到对应的 effect 副作用函数,然后重新执行。

reactive

reactive 会返回如下一个 Proxy 对象

constreactive=(target)=>{
returnnewProxy(target,{
get(target,key,receiver){
constres=Reflect.get(target,key,receiver);

track(target,key);//收集依赖

if(isObject(res)){
//如果当前获取的属性值是一个对象,则继续将为此对象创建Proxy代理
returnreactive(res);
}

returnres;
},

set(target,key,value,receiver){
Reflect.set(target,key,value,receiver);
trigger(target,key);//依赖更新
},
});
};

effect

letactiveEffect;
functioneffect(fn){
const_effect=functionreactiveEffect(){
activeEffect=_effect;
fn();
};

_effect();
}

首先定义全局的 activeEffect,它永远指向当前正在执行的 effect 副作用函数。effect 为 fn 创建一个内部的副作用函数,然后立即执行,此时会触发对象的 get 操作,调用 track() 方法。

effect(()=>{
//effect的立即执行会访问state.counter,触发了对象的get操作。
document.querySelector("#app").innerHTML=state.counter;
});

track

track 会建立一个 对象(state) => 属性(counter) => effect 的一个依赖关系

consttargetMap=newWeakMap();
functiontrack(target,key){
if(!activeEffect){
return;
}

letdepsMap=targetMap.get(target);
if(!depsMap){
targetMap.set(target,(depsMap=newMap()));
}

letdep=depsMap.get(key);
if(!dep){
depsMap.set(key,(dep=newSet()));
}

if(!dep.has(activeEffect)){
dep.add(activeEffect);
}
}

执行完成成后我们得到一个如下的数据结构:

[//map集合
{
key:{counter:1}//state对象,
value:[//map集合
{
key:"counter",
value:[//set
functionreactiveEffect(){}//effect副作用函数
],
}
],
},
];

注意:当我们调用 effect 时,会将当前的副作用函数赋值给全局的 activeEffect,所以此时我们可以正确关联其依赖。

trigger

当我们给 state.counter 赋值的时候就会触发代理对象的 set 操作,从而调用 trigger 方法

setTimeout(()=>{
//给counter属性赋值会触发set操作
state.counter+=1;
},2000);
functiontrigger(target,key){
constdepsMap=targetMap.get(target);
if(!depsMap)return;

consteffects=depsMap.get(key);
effects&&effects.forEach((effect)=>effect());
}

若想继续学习更多相关知识,请继续关注亿速云网站,小编会继续努力为大家带来更多实用的文章!

本文:Vue3的响应式原理是什么的详细内容,希望对您有所帮助,信息来源于网络。
上一篇:Spring  AOP如何使用下一篇:

22 人围观 / 0 条评论 ↓快速评论↓

(必须)

(必须,保密)

阿狸1 阿狸2 阿狸3 阿狸4 阿狸5 阿狸6 阿狸7 阿狸8 阿狸9 阿狸10 阿狸11 阿狸12 阿狸13 阿狸14 阿狸15 阿狸16 阿狸17 阿狸18