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)容,更多關(guān)于Vue.js無限遞歸的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
基于Vue實現(xiàn)HTML轉(zhuǎn)PDF并導出
這篇文章主要為大家介紹了三種方法,可以實現(xiàn)將HTML頁面轉(zhuǎn)為PDF并實現(xiàn)下載。文中的示例代碼講解詳細,感興趣的小伙伴可以學習一下2022-04-04

