vue.js

关注公众号 jb51net

关闭
首页 > 网络编程 > JavaScript > javascript类库 > vue.js > Vue.js无限递归

Vue.js设计与实现无限递归学习总结

作者:玛拉_以琳

这篇文章主要为大家介绍了Vue.js设计与实现无限递归学习总结,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

栈溢出

const data = { foo: 1 }
const obj = new Proxy(data, {/*...*/})
effect(() => obj.foo = obj.foo + 1)

此项操作会引起栈溢出:

Uncaught RangeError: Maximum call sack size exceeded

在此操作中, 会先读取obj.foo的值, 这会触发track操作, 将副作用函数入栈, 此时有加一并赋值, 此时会触发trigger操作, 将副作用函数出栈并执行, 在这种情况下, 该副作用函数还在执行中, 又开始下一次的执行, 导致无限递归调用自己导致栈溢出报错.

在这个操作中读取与设置的是同一个副作用函数activeEffect, 因此在trigger要触发时添加条件: 如果trigger触发的副作用函数与当前执行的副作用函数相同, 则不触发执行:

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())
}

目前为止响应式完整代码

// 储存副作用函数的桶
  const bucket = new WeakMap()
  // 用于储存被注册的副作用的函数
  let activeEffect = undefined
  // 副作用函数栈
  const effectStack = []
  function cleanup (effectFn) {
    for (let itme of effectFn.deps) {
      itme.delete(effectFn)
    }
    effectFn.deps.length = []
  }
  function effect (fn) {
    const effectFn = () => {
        cleanup(effectFn)
        // 调用当前的副作用函数时, 赋值给 全局变量
        activeEffect = effectFn
        // 在调用副作用函数之前将该函数压入栈
        effectStack.push(effectFn)
        fn()

以上就是Vue.js设计与实现无限递归学习总结的详细内容,更多关于Vue.js无限递归的资料请关注脚本之家其它相关文章!

您可能感兴趣的文章:
阅读全文