Vue-Router 中的路由更改后仍然显示上一个视图

Previous view still diplays after route changes in Vue-Router

我有一个带有 Vue-Router v4 的 Vue3 SPA,当推送新路由时,会显示新视图,而旧视图仍会保留一小段时间。它创建了一个非常丑陋的“闪烁”效果(见下面的 Gif)

我不知道是什么原因造成的,而且我找不到关于 Google/Whosebug 的太多信息。这让我觉得它来自我的实现,而不是来自 Vue-Router 的错误。

这是我的代码 router.js:


import routes from './routes';

import store from '~/store';

// Function that takes the array of a user's rights and another array of the rights required to access a page
// Return true if the user has all rights required, false otherwise
let checker = (arr, target) => target.every(v => arr.includes(v));

const router = createRouter({
  history: createWebHashHistory(),
  routes,
});

router.beforeEach((to) => {
  if (to.meta.requiresAuth && !getToken().accessToken) {
    return {
      path: '/login',
      // save the location we were at to come back later
      query: { redirect: to.fullPath },
    };
  } else if (to.meta.requiresRights && Array.isArray(to.meta.requiresRights)) {
    const userRights = store.state.auth.user.rights;
    const requiredRights = to.meta.requiresRights;

    return checker(userRights, requiredRights);
  } else {
    return true;
  }
});

这些是我的路线:

import SideNavigation from '~/components/layout/SideNavigation.vue';
import Footer from '~/components/layout/Footer.vue';
import Access from '~/views/Access.vue';
import Agents from '~/views/Agents.vue';
import Articles from '~/views/Articles.vue';
import ArticlesHistory from '~/views/ArticlesHistory.vue';
import EventsHistory from '~/views/EventsHistory.vue';
import Home from '~/views/Home.vue';
import Roles from '~/views/Roles.vue';
import Warehouse from '~/views/Warehouse.vue';
import WarehouseHistory from '~/views/WarehouseHistory.vue';
import Stocks from '~/views/Stocks.vue';
import TimeTable from '~/views/TimeTable.vue';
import Users from '~/views/Users.vue';
import Login from '~/views/Login.vue';
import Inventory from '~/views/Inventory.vue';
import NotFoundComponent from '~/views/NotFoundComponent.vue';

const routes = [
  {
    path: '/access/:id',
    name: 'access',
    components: {
      default: Access,
      SideNavigation,
      Footer,
    },
    meta: {
      requiresAuth: true,
      requiresRights: ['manage_agents_gestion'],
    },
  },
  {
    path: '/agents',
    name: 'agents',
    components: {
      default: Agents,
      SideNavigation,
      Footer,
    },
    meta: {
      requiresAuth: true,
      requiresRights: ['manage_agents_gestion'],
    },
  },
  {
    path: '/articles',
    name: 'articles',
    components: {
      default: Articles,
      SideNavigation,
      Footer,
    },
    meta: {
      requiresAuth: true,
      requiresRights: ['manage_articles_gestion'],
    },
  },
  {
    path: '/articles-historique',
    name: 'articlesHistorique',
    components: {
      default: ArticlesHistory,
      SideNavigation,
      Footer,
    },
    meta: {
      requiresAuth: true,
    },
  },
  {
    path: '/evenements-historique',
    name: 'evenements',
    components: {
      default: EventsHistory,
      SideNavigation,
      Footer,
    },
    meta: {
      requiresAuth: true,
    },
  },
  {
    path: '/',
    name: 'home',
    components: {
      default: Home,
      SideNavigation,
      Footer,
    },
    meta: {
      requiresAuth: true,
    },
  },
  {
    path: '/login',
    name: 'login',
    components: {
      default: Login,
    },
  },
  {
    path: '/roles/agents',
    name: 'rolesAgents',
    components: {
      default: Roles,
      SideNavigation,
      Footer,
    },
    props: {
      default: {
        roleType: 1,
      },
    },
    meta: {
      requiresAuth: true,
    },
  },
  {
    path: '/roles/users',
    name: 'rolesUsers',
    components: {
      default: Roles,
      SideNavigation,
      Footer,
    },
    props: {
      default: {
        roleType: 0,
      },
    },
    meta: {
      requiresAuth: true,
    },
  },
  {
    path: '/warehouse/:id',
    name: 'warehouse',
    components: {
      default: Warehouse,
      SideNavigation,
      Footer,
    },

    meta: {
      requiresAuth: true,
    },
  },
  {
    path: '/warehouse/:id/stock',
    name: 'warehouseStock',
    components: {
      default: Stocks,
      SideNavigation,
      Footer,
    },

    meta: {
      requiresAuth: true,
    },
  },
  {
    path: '/warehouse/:id/history',
    name: 'warehouseHistory',
    components: {
      default: WarehouseHistory,
      SideNavigation,
      Footer,
    },

    meta: {
      requiresAuth: true,
    },
  },
  {
    path: '/warehouse/:id/invent-historique',
    name: 'inventaires',
    components: {
      default: Inventory,
      SideNavigation,
      Footer,
    },
  },
  {
    path: '/timetable',
    name: 'timetable',
    components: {
      default: TimeTable,
      SideNavigation,
      Footer,
    },
    meta: {
      requiresAuth: true,
    },
  },
  {
    path: '/users',
    name: 'users',
    components: {
      default: Users,
      SideNavigation,
      Footer,
    },
    meta: {
      requiresAuth: true,
      requiresRights: ['manage_users_gestion'],
    },
  },

  // 404
  { path: '/:pathMatch(.*)', component: NotFoundComponent },
];

export default routes;

这是路由器视图:

 <div class="side-nav-container">
      <div class="side-nav">
        <router-view
          name="SideNavigation"
          link-active-class="is-active"
        />
      </div>
    </div>
    <div
      class="container flex flex-column"
      style="width: 100%"
    >
      <div class="flex-grow-1">
        <router-view v-slot="{ Component }">
          <transition name="el-fade-in-linear">
            <component :is="Component" />
          </transition>
        </router-view>
      </div>

      <div class="footer-container">
        <Footer />
      </div>
    </div>

出现此问题的原因是 Vue 默认使用 in-out 模式进行转换。如果你改变模式 out-in 它应该是固定的。

<transition name="el-fade-in-linear" mode="out-in">
  <component :is="Component" />
</transition>

As described in the documentation:

  • in-out: New element transitions in first, then when complete, the current element transitions out.
  • out-in: Current element transitions out first, then when complete, the new element transitions in.