vue響應(yīng)式Object代理對(duì)象的修改和刪除屬性
正文
上一篇文章我們學(xué)習(xí)了如何代理對(duì)象的讀取,下面我們學(xué)習(xí)如何代理對(duì)象的修改和刪除屬性。
set
set就是修改代理的屬性,按照我們之前寫(xiě)的reactive,它大概是這樣的
const ITERATE_KEY=symbol()
const p = new Proxy(obj,{
set(target,key,newVal,receiver){
const res = Reflect.set(target,key,newVal,receiver)
trigger(target,key)
return res
}
}
細(xì)心的朋友應(yīng)該發(fā)現(xiàn)了,我專(zhuān)門(mén)把ITERATE_KEY也加進(jìn)來(lái)了,但是在set中并沒(méi)有使用,難道是多余的?
這里其實(shí)有一個(gè)小坑,就是如果曾經(jīng)對(duì)對(duì)象使用過(guò)for ... in,這里會(huì)出現(xiàn)2種情況:
- 如果我們新增了一個(gè)屬性,那么我們是不是應(yīng)該重新運(yùn)行一次
for ... in的副作用函數(shù)。 - 如果我們只是修改某個(gè)屬性而不是新增,那么我們就不應(yīng)該重新運(yùn)行
for ... in的副作用函數(shù). 所以我們需要判斷一下它是新增還是修改
//定義常量,在ts中可以使用枚舉
const TriggerType = {
SET:'SET',
ADD:'ADD'
}
const p = new Proxy(obj,{
set(target,key,newVal,receiver){
//判斷新增還是修改
const type = Object.prototype.hasOwnProperty.call(target,key)
? TriggerType.SET
: TriggerType.ADD
const res = Reflect.set(target,key,newVal,receiver)
trigger(target,key,type)
return res
}
}
同時(shí),對(duì)應(yīng)trigger函數(shù)中,我們也需要根據(jù)type讀取ITERATE_KEY對(duì)應(yīng)的副作用函數(shù).
const trigger = (target,key,type)=>{
const depsMap = targetMap.get(target)
if(!depsMap){
return
}
const effects = depsMap.get(key)
// 再次去重
const needToRun = new Set()
if(effects){
effects.forEach(e=> e!==activeEffect
? needToRun.add(e)
: ''
)
}
if(type === TriggerType.ADD){
const otherEffects = depsMap.get(ITERATE_KEY)
if(otherEffects){
otherEffects.forEach(e=> e!==activeEffect
? needToRun.add(e)
: ''
)
}
}
if(needToRun.length){
needToRun.forEach(fn=> fn?.options?.scheduler ? fn.options.scheduler(fn) : fun())
}
}
這樣,我們只在新增的時(shí)候才會(huì)調(diào)用for ... in的副作用函數(shù)。
delete
刪除的時(shí)候,之前貌似沒(méi)寫(xiě)過(guò)。這里需要注意2個(gè)點(diǎn)。
- 保證屬性刪除之后才運(yùn)行副作用,這里從邏輯上講我們最好先驗(yàn)證這個(gè)屬性是否存在,避免報(bào)錯(cuò)。
- 刪除時(shí)也要運(yùn)行
for ... in的副作用函數(shù)
因此我們這樣定義,給TriggerType新增一個(gè)類(lèi)型DEL
const TriggerType = {
SET:'SET',
ADD:'ADD',
DEL:'DELETE'
}
然后,我們開(kāi)始攔截刪除屬性的操作,查一下之前的Proxy內(nèi)部方法的表,我們可以得知,刪除屬性對(duì)應(yīng)著deleteProperty方法。
const p = new Proxy(obj,{
deleteProperty(target,key){
//判斷屬性存在,你總不能刪除一個(gè)不存在的屬性吧
const hadKey = Object.prototype.hasOwnProperty.call(target,key)
const res = Reflect.deleteProperty(target,key)
if(res && hadKey){
trigger(target,key,TriggerType.DEL)
}
return res
}
}
對(duì)應(yīng)trigger函數(shù)中,我們小修改一下,其他邏輯不變
// 刪除這句
- if(type === TriggerType.ADD){
// 改為
+ if([TriggerType.ADD,TriggerType.DEL].includes(type)){
這樣就可以實(shí)現(xiàn)響應(yīng)式對(duì)象的刪除屬性。
其實(shí)原文中并沒(méi)有使用Array.includes,但我覺(jué)得其實(shí)我們應(yīng)該使用最新的語(yǔ)法,現(xiàn)在瀏覽器環(huán)境對(duì)這些新語(yǔ)法支持度已經(jīng)很好了(如果你要兼容IE當(dāng)我沒(méi)說(shuō))。
這一篇就完結(jié)了,總結(jié)一下就是如何對(duì)對(duì)象的讀取屬性、修改屬性、刪除屬性進(jìn)行代理,大概了解vue3中對(duì)于對(duì)象的處理。
但是這里還沒(méi)有結(jié)束,后續(xù)會(huì)講一些邊際條件,以及如何合理的響應(yīng)數(shù)據(jù)變化和操作,合理也就是優(yōu)化,盡可能的減少多余的響應(yīng)。
更多關(guān)于vue響應(yīng)式Object修改刪除的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
vue 框架下自定義滾動(dòng)條(easyscroll)實(shí)現(xiàn)方法
這篇文章主要介紹了vue 框架下自定義滾動(dòng)條(easyscroll)實(shí)現(xiàn)方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-08-08
使用vue實(shí)現(xiàn)通過(guò)變量動(dòng)態(tài)拼接url
這篇文章主要介紹了使用vue實(shí)現(xiàn)通過(guò)變量動(dòng)態(tài)拼接url,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-07-07
vue 2.0項(xiàng)目中如何引入element-ui詳解
element-ui是一個(gè)比較完善的UI庫(kù),但是使用它需要有一點(diǎn)vue的基礎(chǔ),下面這篇文章主要給大家介紹了關(guān)于在vue 2.0項(xiàng)目中如何引入element-ui的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考借鑒,下面來(lái)一起看看吧。2017-09-09
Vue項(xiàng)目中接口調(diào)用的詳細(xì)講解
應(yīng)公司需求,接口需要對(duì)接vue,記錄一下碰到的問(wèn)題,下面這篇文章主要給大家介紹了關(guān)于Vue項(xiàng)目中接口調(diào)用的詳細(xì)講解,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-07-07
前端vue面試總問(wèn)watch和computed區(qū)別及建議總結(jié)
在現(xiàn)代前端的面試中,vue和react是面試過(guò)程中基本必問(wèn)的技術(shù)棧,其中Vue響應(yīng)式話(huà)題,watch和computed是面試官非常喜歡聊的主題,雖然watch和computed它們都用于監(jiān)聽(tīng)數(shù)據(jù)的變化,但它們?cè)趯?shí)現(xiàn)原理、使用場(chǎng)景和行為上有著顯著的區(qū)別,本文將深入探討,并提供一些面試過(guò)程中的建議2023-10-10
vue實(shí)戰(zhàn)中的一些實(shí)用小魔法匯總
這篇文章主要給大家介紹了關(guān)于vue實(shí)戰(zhàn)中一些實(shí)用小魔法的相關(guān)資料,這些技巧和竅門(mén),可以幫助你成為更好的Vue開(kāi)發(fā)人員,需要的朋友可以參考下2021-06-06
vue中生成條形碼(jsbarcode)和二維碼(qrcodejs2)的簡(jiǎn)單示例
在vue項(xiàng)目中難免遇到有要生成條形碼或者二維碼的功能需求,下面這篇文章主要給大家介紹了關(guān)于vue中生成條形碼(jsbarcode)和二維碼(qrcodejs2)的相關(guān)資料,文中通過(guò)圖文介紹的非常詳細(xì),需要的朋友可以參考下2022-12-12
在Vue的mounted中仍然加載渲染不出echarts的方法問(wèn)題
這篇文章主要介紹了在Vue的mounted中仍然加載渲染不出echarts的方法問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-03-03

