Vue嵌套路由导致父组件重复渲染BUG

5,729 阅读1分钟

场景

嵌套路由结构

    {
        //一级路由
        path: "/basinMgr",
        name: "basinMgr",
        component: () => import('./pages/basinMgr.vue'),
        meta: {
            level: 13,
            flag: true,
        },
        children: [
            {
                //1.tab1页面
                path: "/tab1List",
                name: "tab1List",
                component: () => import('./pages/tab1List.vue'),
                meta: {
                    level: 13,
                    flag: true,
                },
            },
            {
                //2.tab2页面
                path: "/tab2List",
                name: "tab2List",
                component: () => import('./pages/tab2List.vue'),
                meta: {
                    level: 13,
                    flag: true,
                },
            },
  
        ]
    },

一级的router-view代码如下:

<template>
  <i-body>
    <keep-alive>
      <router-view
        v-if="$route.meta.flag"
      />
    </keep-alive>
    <router-view
      v-if="!$route.meta.flag"
    />
  </i-body>
</template>

二级router-view在basinMgr组件里,代码如下:

<div>
  <keep-alive>
     <router-view v-if="$route.meta.flag" />
  </keep-alive>
  <router-view v-if="!$route.meta.flag" />
</div>

页面结构

image.png

问题描述

点击tab标签调用该方法跳转页面

this.$router.push({ name: 'tab1'})

然后出现了一个意料之外的问题,Vue总是会把basinMgr组件重新加载一遍,导致每次点击树形控件都要重新获取数据。

image.png

根据官方说法basinMgr中的tree应该是被复用的,不应该重新加载。所以蒙了~

解决方案

由于路由都是通过router-view渲染的,只要保证每次渲染时router-viewkey值不变,该组件就不会重新渲染。

所以在一级路由加上key值,确保二级路由渲染的时候该key值是一样的。

上代码:

一级路由改为:(主要增加了key)

<template>
  <i-body>
    <keep-alive>
      <router-view
        v-if="$route.meta.flag"
        :key="key"
      />
    </keep-alive>
    <router-view
      v-if="!$route.meta.flag"
      :key="key"
    />
  </i-body>
</template>
<script>
export default {
  computed: {
    key() {
      return this.$route.meta.activeMenuName;
    }
  }
};
</script>

路由结构改为:(主要增加了activeMenuName)

    {
        //一级路由
        path: "/basinMgr",
        name: "basinMgr",
        component: () => import('./pages/basinMgr.vue'),
        meta: {
            level: 13,
            flag: true,
            activeMenuName: "basinMgr"
        },
        children: [
            {
                //1.tab1页面
                path: "/tab1List",
                name: "tab1List",
                component: () => import('./pages/tab1List.vue'),
                meta: {
                    level: 13,
                    flag: true,
                    activeMenuName: "basinMgr"
                },
            },
            {
                //2.tab2页面
                path: "/tab2List",
                name: "tab2List",
                component: () => import('./pages/tab2List.vue'),
                meta: {
                    level: 13,
                    flag: true,
                    activeMenuName: "basinMgr"
                },
            },
  
        ]
    },

成功~

总结

router-viewkey的唯一性会导致“根据参数动态渲染路由”时无法复用组件。想要复用某组件,就保证router-view里按需赋予它该有的keykey不变就不会重新渲染组件。