在 Vue 项目开发中,我们经常会遇到多个菜单路由对应同一个业务组件的场景,比如路由 article/1、article/2…article/6 全部指向 Article 组件。
默认情况下,Vue Router 会复用组件实例来提升性能,这就导致切换路由时:
✅ 路由地址变化
❌ 页面不重新渲染、数据不更新
❌ 组件生命周期(created/mounted)不重新执行
本文给大家分享一个简单、通用、零侵入的解决方案,完美解决这个痛点。
一、核心解决方案
我们通过 控制 <router-view> 销毁 / 重建 的方式强制刷新页面,配合 Vue 的 provide/inject 实现全局刷新方法调用,分三步实现:
步骤 1:根组件 App.vue 配置全局刷新方法
在根组件中定义刷新逻辑,通过 provide 注入到所有子组件,同时用 v-if 控制路由组件的渲染状态。
vue
<!-- App.vue -->
<template>
<!-- 核心:v-if 控制组件销毁与重建 -->
<router-view v-if="isReload" />
</template>
<script setup>
import { provide, ref, nextTick } from 'vue';
// 控制路由组件的渲染状态
const isReload = ref(true);
// 刷新方法:先销毁组件,再重建组件
const reload = () => {
// 1. 销毁组件
isReload.value = false;
// 2. 等待DOM更新完成后,重建组件(必须用nextTick)
nextTick(() => {
isReload.value = true;
});
};
// 注入刷新方法,所有子组件都可以调用
provide('reload', reload);
</script>
步骤 2:路由配置(多个路径对应同一组件)
这是我们的业务路由配置,多个不同 path 映射同一个 Article 组件,也是问题产生的根源:
js
// router/index.js
// 路由懒加载工具函数(自行封装)
const lazyLoading = (page) => () => import(`@/views/${page}.vue`);
const routes = [
{
name: 'article.index1',
path: 'article/1',
component: lazyLoading('Article'),
meta: { title: '新闻资讯' },
},
{
name: 'article.index2',
path: 'article/2',
component: lazyLoading('Article'),
meta: { title: '消息通知' },
},
{
name: 'article.index3',
path: 'article/3',
component: lazyLoading('Article'),
meta: { title: '活动回顾' },
},
// 其余路由同理...
];
步骤 3:业务组件 Article.vue 触发刷新
在目标组件中,通过 inject 接收刷新方法,监听路由变化,切换路由时自动触发刷新。
选项式 API 写法(兼容大部分项目)
vue
<!-- Article.vue -->
<script>
export default {
// 接收根组件注入的刷新方法
inject: ['reload'],
data() {
return {
page: 1
};
},
watch: {
// 监听分页变化(业务逻辑,可选)
'pagination.page'() {
this.page = this.pagination.page;
},
// 核心:监听路由变化,切换时立即刷新页面
'$route'() {
this.reload();
},
},
};
</script>
组合式 API 写法(Vue3 推荐)
vue
<!-- Article.vue -->
<script setup>
import { inject, watch } from 'vue';
import { useRoute } from 'vue-router';
// 获取刷新方法
const reload = inject('reload');
const route = useRoute();
// 监听路由变化,触发刷新
watch(
() => route.path,
() => {
reload();
}
);
</script>
二、方案原理讲解
- 为什么切换路由不刷新?Vue Router 默认机制:路由切换但组件相同时,复用组件实例,不会执行销毁和重建,生命周期只触发一次。
- 本方案为什么能生效?
- 通过
v-if="false"销毁<router-view>内的组件 nextTick保证 DOM 完成销毁后,再通过v-if="true"重建组件- 组件重建会完整执行所有生命周期,页面自然刷新
- 通过
- 为什么用 provide/inject?全局注入一次刷新方法,所有业务组件都能直接调用,无需逐层传参,代码更简洁。
三、关键注意事项
- 必须使用 nextTick销毁和重建的逻辑必须异步执行,如果同步写,Vue 会合并更新,刷新失效。
- 适用场景专门解决 同组件、多路由路径 切换不刷新的问题(如文章列表、分类页面等)。
- 性能友好仅在路由切换时执行一次销毁重建,对项目性能无明显影响。
四、总结
这个方案是 Vue 项目中解决同组件路由切换不刷新的最优实践之一:
✅ 代码极简,3 行核心逻辑
✅ 全局通用,一次配置多处使用
✅ 无第三方依赖,零侵入
✅ 兼容 Vue3 所有写法(选项式 / 组合式)
直接复制代码到项目中,即可完美解决 article/1、article/2 这类路由切换不刷新的问题!
正文完
可以使用微信扫码关注公众号(ID:xzluomor)