Vue 解决同组件多路由路径(article/1、article/2)切换不刷新问题

9次阅读
没有评论

在 Vue 项目开发中,我们经常会遇到多个菜单路由对应同一个业务组件的场景,比如路由 article/1article/2article/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>

二、方案原理讲解

  1. 为什么切换路由不刷新?Vue Router 默认机制:路由切换但组件相同时,复用组件实例,不会执行销毁和重建,生命周期只触发一次。
  2. 本方案为什么能生效?
    • 通过 v-if="false" 销毁 <router-view> 内的组件
    • nextTick 保证 DOM 完成销毁后,再通过 v-if="true" 重建组件
    • 组件重建会完整执行所有生命周期,页面自然刷新
  3. 为什么用 provide/inject?全局注入一次刷新方法,所有业务组件都能直接调用,无需逐层传参,代码更简洁。

三、关键注意事项

  1. 必须使用 nextTick销毁和重建的逻辑必须异步执行,如果同步写,Vue 会合并更新,刷新失效。
  2. 适用场景专门解决 同组件、多路由路径 切换不刷新的问题(如文章列表、分类页面等)。
  3. 性能友好仅在路由切换时执行一次销毁重建,对项目性能无明显影响。

四、总结

这个方案是 Vue 项目中解决同组件路由切换不刷新最优实践之一

✅ 代码极简,3 行核心逻辑

✅ 全局通用,一次配置多处使用

✅ 无第三方依赖,零侵入

✅ 兼容 Vue3 所有写法(选项式 / 组合式)

直接复制代码到项目中,即可完美解决 article/1article/2 这类路由切换不刷新的问题!

正文完
可以使用微信扫码关注公众号(ID:xzluomor)
post-qrcode
 0
评论(没有评论)
验证码