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.
我有一个带有 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.