问题

利用 router-view 路由嵌套进行 page1page2 页面切换时,service 页面也会重新渲染。

/company/service/page1                   /company/service/page2
+---------------------+                  +---------------------+
| company             |                  | company             |
| +-----------------+ |                  | +-----------------+ |
| | service         | |  +------------>  | | service         | |
| | +-------------+ | |                  | | +-------------+ | |
| | | page1       | | |                  | | | page2       | | |
| | |             | | |                  | | |             | | |
| | |             | | |                  | | |             | | |
| | +-------------+ | |                  | | +-------------+ | |
| +-----------------+ |                  | +-----------------+ |
+---------------------+                  +---------------------+
// layout/company.vue  一级嵌套
<template>
  <section class="company">
    <transition mode="out-in" name="fade-transform">
      <router-view :key="key" />
    </transition>
  </section>
</template>

<script>
export default {
  name: 'company',
  computed: {
    key() {
      return this.$route.path
    }
  }
}
</script>
// layout/service.vue  二级嵌套
<template>
  <section class="service-wrapper">
    <Map2D />
    <router-view :key="key" />
  </section>
</template>

<script>
export default {
  name: 'service',
  computed: {
    key() {
      return this.$route.path
    }
  }
}
</script>
// router
{
    path: '/company',
    component: () => import('@/layout/company'),
    redirect: '/company/service/page1',
    children: [
      {
        path: 'service',
        name: 'service',
        redirect: '/company/service/page1',
        component: () => import('@/layout/service'),
        meta: {
          name: 'service-page'
        },
        children: [
          {
            path: 'page1',
            name: 'page1',
            component: () => import('@/views/page1'),
            meta: {
              name: 'page1'
            }
          },
          {
            path: 'page2',
            name: 'page2',
            component: () => import('@/views/page2'),
            meta: {
              name: 'page2'
            }
          }
        ]
      }
    ]
  },

原因

因为在一级嵌套页面,router-view 有一个 key 属性,如果 key 改变复用视图会重新渲染。
从page1切换到page2时,一级嵌套的 key/company/service/page1/company/service/page2 ,因此 service 重新渲染。

// layout/company.vue  一级嵌套
<template>
  <section class="company">
    <transition mode="out-in" name="fade-transform">
      <router-view :key="key" />  // key 改变会导致复用视图重新渲染
    </transition>
  </section>
</template>

vue-router 官方文档中提到 ↓↓↓
在这里插入图片描述

解决

service 及children 路由上添加一个标识 routerViewKey ,一级嵌套页面中的 router-view 属性 key 改为 routerViewKey 即可,这样当页面切换时,复用也不会重新渲染。

// router
{
    path: '/company',
    component: () => import('@/layout/company'),
    redirect: '/company/service/page1',
    children: [
      {
        path: 'service',
        name: 'service',
        redirect: '/company/service/page1',
        component: () => import('@/layout/service'),
        meta: {
          name: 'service',
          routerViewKey: 'service-page'
        },
        children: [
          {
            path: 'page1',
            name: 'page1',
            component: () => import('@/views/page1'),
            meta: {
              name: 'page1',
          	  routerViewKey: 'service-page'
            }
          },
          {
            path: 'page2',
            name: 'page2',
            component: () => import('@/views/page2'),
            meta: {
              name: 'page2',
              routerViewKey: 'service-page'
            }
          }
        ]
      }
    ]
  },
// layout/company.vue  一级嵌套
<template>
  <section class="company">
    <transition mode="out-in" name="fade-transform">
      <router-view :key="key" />  // key 改变会导致页面重新渲染
    </transition>
  </section>
</template>

<script>
export default {
  name: 'company',
  computed: {
    key() {
      return this.$route.meta.routerViewKey || this.$route.path  // 优先赋值为 routerViewKey 
    }
  }
}
</script>

参考:
VUE嵌套路由导致父组件重复渲染BUG(虚惊一场)
vue router 强制在复用的视图之间进行过渡

Logo

前往低代码交流专区

更多推荐