vue3 vue-router嵌套两级路由时,每一级路由都使用transition+keep-alive时,二级路由之间切换离场动效正常,一级路由之间切换会导致离场的页面组件离场动效重复1遍

vue3中使用vue-router嵌套两级路由时,每一级路由都使用transition+keep-alive时,二级路由之间切换离场动效正常,一级路由之间切换会导致离场的页面组件离场动效重复1遍,即播放了两遍离场动效

场景复现

问题场景和这篇文章中的是类似的:同时使用transition+keep-alive时二级路由之间跳转会导致页面组件重复渲染,下面我就引用这篇文章中举的例子了

  • 一级路由App.vue(菜单A、菜单B)
	<template>
	<div>
		<router-link to="/MenuAChild1">菜单Arouter-link>
	div>
	<div>
		<router-link to="/MenuBChild1">菜单Brouter-link>
	div>
	<div style="margin-top:1em;">
		<router-view v-slot="{ Component }">
			<transition>
				<keep-alive>
					<component :is="Component" />
				keep-alive>
			transition>
		router-view>
	div>
template>

  • 菜单A.vue(菜单B一样),里面嵌套二级路由
<template>
	<router-view v-slot="{ Component }">
		<transition name="left2right">
			<keep-alive>
				<component :is="Component" />
			keep-alive>
		<transition name="mainRouter">
	router-view>
template>
<style>
.left2right-enter-from,
.left2right-leave-to {
  transform: translateX(-120%);
}

.left2right-enter-to,
.left2right-leave-from {
  transform: translateX(0%);
}

.left2right-enter-active {
  transition: transform 1s linear;
  transition-delay: 0.3s;
}
.left2right-leave-active {
  transition: transform 0.3s linear;
}
style>

问题

    1. 一级菜单之间切换时,旧页面会走两次离场动效
    1. 二级菜单之间的切换正常

问题出现原因分析

    1. router-view 有两级嵌套,每一级嵌套都使用keep-alive 使其缓存
    1. 二级菜单切换时,只会触发二级router-viewkeep-alive ,所以旧view 离场动效正常
    1. 一级菜单切换时,两个router-viewkeep-alive 都触发,所以旧view 的离场动效触发两次

解决方案

    1. 一级菜单按需使用keep-alive ,当一级菜单切换时,激活旧viewkeep-alive,使旧view的二级route-view正常走离场动效
    1. 走完旧view离场动效走后,再屏蔽keep-alive,删除掉旧view

解决细节:

    1. 只有二级routekeep-alive, 保证二级路由的页面正常走离场动效果
    1. 监听路由变化(使用onBeforeRouteUpdate(to, from) ),当切换一级route变化时(即to.matched[1] !== from.matched[1]),暂时让当前Component旧view)的 KeepAlive激活一下
    1. 重点!!二级route的离场动效正常走完
    1. 当旧二级route的离场动效走完后,就会触发nextTicknextTick中使KeepAlivefalse, 则会将旧一级routeview缓存删除
// 一级路由页面App.vue中
<template>
  <router-view v-slot="{ Component }">
    <transition>
      <keep-alive
        :include="keepAlive ? Component : ''"
      >
        <component :is="Component" />
      </keep-alive>
    </transition>
  </router-view>
</template>
const keepAlive = ref(false);
onBeforeRouteUpdate((from, to)=> {
	if (from && (to.matched.length > 2 && from.matched.length > 2) && to.matched[1] !== from.matched[1]) {
		keepAlive.value = true;
		nextTick(() => {
			keepAlive.value = false;
		});
	}
});

不知道自己的理解或者表述有没有问题,希望大家指出问题哈!

你可能感兴趣的:(vue.js,javascript,前端)