Vue.js設(shè)計(jì)與實(shí)現(xiàn)無限遞歸學(xué)習(xí)總結(jié)
棧溢出
const data = { foo: 1 }
const obj = new Proxy(data, {/*...*/})
effect(() => obj.foo = obj.foo + 1)此項(xiàng)操作會(huì)引起棧溢出:
Uncaught RangeError: Maximum call sack size exceeded
在此操作中, 會(huì)先讀取obj.foo的值, 這會(huì)觸發(fā)track操作, 將副作用函數(shù)入棧, 此時(shí)有加一并賦值, 此時(shí)會(huì)觸發(fā)trigger操作, 將副作用函數(shù)出棧并執(zhí)行, 在這種情況下, 該副作用函數(shù)還在執(zhí)行中, 又開始下一次的執(zhí)行, 導(dǎo)致無限遞歸調(diào)用自己導(dǎo)致棧溢出報(bào)錯(cuò).
在這個(gè)操作中讀取與設(shè)置的是同一個(gè)副作用函數(shù)activeEffect, 因此在trigger要觸發(fā)時(shí)添加條件: 如果trigger觸發(fā)的副作用函數(shù)與當(dāng)前執(zhí)行的副作用函數(shù)相同, 則不觸發(fā)執(zhí)行:
function trigger (target, key) {
const depsMap = bucket.get(target)
if (!depsMap) return
const effects = depsMap.get(key)
const effectsToRun = new Set()
effects && effects.forEach(effectFn => {
if (effectFn !== activeEffect) {
effectsToRun.add(effectFn)
}
})
effectsToRun.forEach(effectFn => effectFn())
}目前為止響應(yīng)式完整代碼
// 儲(chǔ)存副作用函數(shù)的桶
const bucket = new WeakMap()
// 用于儲(chǔ)存被注冊(cè)的副作用的函數(shù)
let activeEffect = undefined
// 副作用函數(shù)棧
const effectStack = []
function cleanup (effectFn) {
for (let itme of effectFn.deps) {
itme.delete(effectFn)
}
effectFn.deps.length = []
}
function effect (fn) {
const effectFn = () => {
cleanup(effectFn)
// 調(diào)用當(dāng)前的副作用函數(shù)時(shí), 賦值給 全局變量
activeEffect = effectFn
// 在調(diào)用副作用函數(shù)之前將該函數(shù)壓入棧
effectStack.push(effectFn)
fn()以上就是Vue.js設(shè)計(jì)與實(shí)現(xiàn)無限遞歸學(xué)習(xí)總結(jié)的詳細(xì)內(nèi)容,更多關(guān)于Vue.js無限遞歸的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
vue.js watch經(jīng)常失效的場(chǎng)景與解決方案
這篇文章主要給大家介紹了關(guān)于vue.js watch經(jīng)常失效的場(chǎng)景與解決方案,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-01-01
vue實(shí)現(xiàn)滑動(dòng)超出指定距離回頂部功能
這篇文章主要為大家詳細(xì)介紹了vue實(shí)現(xiàn)滑動(dòng)超出指定距離回頂部功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-07-07
Vue router傳遞參數(shù)并解決刷新頁面參數(shù)丟失問題
這篇文章主要介紹了Vue router傳遞參數(shù)并解決刷新頁面參數(shù)丟失問題,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-12-12
vue大型項(xiàng)目之分模塊運(yùn)行/打包的實(shí)現(xiàn)
這篇文章主要介紹了vue大型項(xiàng)目之分模塊運(yùn)行/打包的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-09-09
修改vue源碼實(shí)現(xiàn)動(dòng)態(tài)路由緩存的方法
這篇文章主要介紹了修改vue源碼實(shí)現(xiàn)動(dòng)態(tài)路由緩存的方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-01-01
vue3+ts+Vuex中使用websocket協(xié)議方式
這篇文章主要介紹了vue3+ts+Vuex中使用websocket協(xié)議方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-10-10
Vue利用openlayers實(shí)現(xiàn)點(diǎn)擊彈窗的方法詳解
點(diǎn)擊彈窗其實(shí)就是添加一個(gè)彈窗圖層,然后在點(diǎn)擊的時(shí)候讓他顯示出來罷了。本文將利用openlayers實(shí)現(xiàn)這一效果,快跟隨小編一起學(xué)習(xí)一下吧2022-06-06

