记录一次vue2递归死循环排查结果,供以后遇到快速处理

377 阅读1分钟

在控制台报错:

[Vue warn]: You may have an infinite update loop in component render function.

found in 
...

点开报错后,发现是某条赋值语句,奇怪的是在该语句处打断点,发现只赋值了这一次,后续render方法直接疯狂被调用,很快就超过100导致警告。

报错代码:

onInput: (value) => {
    ...
    this.form = value
    ...
}

警告肯定不是这个赋值语句导致的,应该是复制后,导致某个变量被反复修改,频繁触发vue update。但是变量众多,不可能逐一注释尝试,无异于大海捞针。

冷静思考后,在flushSchedulerQueue @vue.runtime.esm.js:4185源码处发现如下逻辑:

...
if (circular[id] > MAX_UPDATE_COUNT) {
    warn('You may have ...')
}
...

在if下一行处打断点,可以看到id=16683,表示id为16683的watcher触发过于频繁。

于是在F12 >> source >> Call Stack往前打断点,寻找该watcher是谁。 在queueWatcher @vue.runtime.esm.js:4239方法的第一行打断点:

function queueWatcher(watcher) {
    var id = watcher.id;
    ...
}

id不是16683的全部都直接忽略放过,当id为16683时,继续在Call Stack往前逐一查看,在项目代码处找到一个setter语句,就是他导致了vue warn!

...
settings.props.rules.push({ ... })

我这边的settings.props.rules是直接取了reactive的rule:settings.props.rules = xxx.yyy.rules,而 xxx是通过props传递进来的。问题清楚了,就是这边在不停地给settings.props.rules赋值,而rules又触发了props更新,既而再次触发vue update,左脚踩右脚,直接螺旋升天。

解决的办法不难:

settings.props.rules = [...xxx.yyy.rules]

不让依赖原变量即可。

本次笔记用于记录排查过程,以便下次如果再遇到时可以快速定位。