VUE3页面报警Maximum recursive updates exceeded in component

VUE3+ANTD做左侧菜单时点击出现警告:

Maximum recursive updates exceeded in component <AMenu>. This means you have a reactive effect that is mutating its own dependencies and thus recursively triggering itself. Possible sources include component template, render function, updated hook or watcher source function.

查原因简单说就是递归出现死循环,页面崩了。

我这个动态菜单在使用MENU时使用了递归来循环children

但是怎么找都找不到比较准确的解决方案,看了好多回答,每一个人的方法都不一样。简直要抓狂。

后来冷静了下,只能用最笨的方法了,一行一行的试

<Menu
    v-model:openKeys="openKeys"
    :theme="theme"
    :selectedKeys="selectedKeys"
    mode="inline"
    style="width: 400px"
    @openChange="onOpenChange"
    @click="handleClick"
>
    <template v-for="item in permissionStore.routes" :key="item.name">
        <template v-if="!item.meta || !item.meta.hidden">
            <!--没有child,子路由-->
            <template 
                v-if="
                    hasOneShowingChild(item.children, item as RouteRecordRaw) &&
                    (!onlyOneChild.children || onlyOneChild.noShowingChildren)
                "
            > 
                <MenuItem >
                    <routerLink :to="item.path">
                        {{ item.meta?.title }}
                    </routerLink>
                </MenuItem>
            </template>
            <template v-else> 
                <SiderbarItem :menuInfo="item" />
            </template>
        </template>
        
    </template>
</Menu>

最终定位是点击父节点时,判断路由的函数:hasOneShowingChild(item.children, item as RouteRecordRaw) && (!onlyOneChild.children || onlyOneChild.noShowingChildren)这个部分导致。函数代码粘过来如下:

const onlyOneChild = ref(); // 临时变量,唯一子路由
function hasOneShowingChild(
    children: RouteRecordRaw[] = [],
    parent: RouteRecordRaw
) {
    // 子路由集合
    const showingChildren = children.filter((route: RouteRecordRaw) => {
        if (route.meta?.hidden) {
            // 过滤不显示的子路由
            return false;
        } else {
            route.meta!.hidden = false;
            // 临时变量(多个子路由 onlyOneChild 变量是用不上的)
            onlyOneChild.value = route;
            return true;
        }
    });
    if (showingChildren.length === 0) {
        onlyOneChild.value = { ...parent, path: "", noShowingChildren: true };
        return true;
    }
    return false;
}

去掉了&&后面的(!onlyOneChild.children || onlyOneChild.noShowingChildren)这个部分,再次点击就没有警告了。

后来思考了下,其他的代码被删除一样崩溃是因为其他的比较简单,而(!onlyOneChild.children || onlyOneChild.noShowingChildren)这个部分的执行包含了过多的循环部分的执行才得出onlyOneChild,还有判断onlyOneChild的children和noShowingChildren,外加下面执行的SiderbarItem 组件里包含了递归,点击了,浏览器就崩溃了。

所以出现这种问题,基本如果不是递归的问题,那也是递归代码周边部分最复杂的部分出现的问题,尝试优化这部分代码。

如果真的找不到问题,那就用一行一行的删除这种笨办法定位。

  • 11
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值