Vue.js設計與實現(xiàn)無限遞歸學習總結(jié)
棧溢出
const data = { foo: 1 }
const obj = new Proxy(data, {/*...*/})
effect(() => obj.foo = obj.foo + 1)此項操作會引起棧溢出:
Uncaught RangeError: Maximum call sack size exceeded
在此操作中, 會先讀取obj.foo的值, 這會觸發(fā)track操作, 將副作用函數(shù)入棧, 此時有加一并賦值, 此時會觸發(fā)trigger操作, 將副作用函數(shù)出棧并執(zhí)行, 在這種情況下, 該副作用函數(shù)還在執(zhí)行中, 又開始下一次的執(zhí)行, 導致無限遞歸調(diào)用自己導致棧溢出報錯.
在這個操作中讀取與設置的是同一個副作用函數(shù)activeEffect, 因此在trigger要觸發(fā)時添加條件: 如果trigger觸發(fā)的副作用函數(shù)與當前執(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())
}目前為止響應式完整代碼
// 儲存副作用函數(shù)的桶
const bucket = new WeakMap()
// 用于儲存被注冊的副作用的函數(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)用當前的副作用函數(shù)時, 賦值給 全局變量
activeEffect = effectFn
// 在調(diào)用副作用函數(shù)之前將該函數(shù)壓入棧
effectStack.push(effectFn)
fn()以上就是Vue.js設計與實現(xiàn)無限遞歸學習總結(jié)的詳細內(nèi)容,更多關于Vue.js無限遞歸的資料請關注腳本之家其它相關文章!
相關文章
vue.js watch經(jīng)常失效的場景與解決方案
這篇文章主要給大家介紹了關于vue.js watch經(jīng)常失效的場景與解決方案,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2021-01-01
Vue router傳遞參數(shù)并解決刷新頁面參數(shù)丟失問題
這篇文章主要介紹了Vue router傳遞參數(shù)并解決刷新頁面參數(shù)丟失問題,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2020-12-12
vue3+ts+Vuex中使用websocket協(xié)議方式
這篇文章主要介紹了vue3+ts+Vuex中使用websocket協(xié)議方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-10-10
Vue利用openlayers實現(xiàn)點擊彈窗的方法詳解
點擊彈窗其實就是添加一個彈窗圖層,然后在點擊的時候讓他顯示出來罷了。本文將利用openlayers實現(xiàn)這一效果,快跟隨小編一起學習一下吧2022-06-06

