Vue Router 是 Vue3 官方路由管理器,负责页面跳转、路由参数传递、权限控制等核心功能,也是 CRM 系统 “多页面结构” 的基础。结合你之前关注的 Pinia + onActivated,下面从「核心定位→基础用法→高级实战→与 Pinia/onActivated 协同」全维度讲解,贴合 CRM 开发场景。

一、核心定位(CRM 开发中为什么必须用?)

CRM 系统本质是 “多页面业务系统”(登录页、工作台、订单列表、订单详情、客户管理等),Vue Router 解决的核心问题:

  1. 页面跳转:比如登录后跳工作台、点击订单跳详情页;
  2. 路由传参:比如订单详情页通过路由获取 orderId
  3. 权限控制:比如未登录用户禁止访问工作台、不同角色访问不同页面;
  4. 页面缓存:配合 KeepAlive 实现列表页缓存(结合 onActivated 刷新)。

二、基础用法(快速上手)

1. 安装与全局注册

bash

运行

# 安装(Vue3 对应 router@4)
npm install vue-router@4

typescript

运行

// src/router/index.ts(路由入口)
import { createRouter, createWebHistory } from 'vue-router';
import Login from '@/views/Login.vue';
import Dashboard from '@/views/Dashboard.vue';
import OrderList from '@/views/OrderList.vue';
import OrderDetail from '@/views/OrderDetail.vue';

// 定义路由规则
const routes = [
  {
    path: '/', // 默认路由
    redirect: '/login' // 重定向到登录页
  },
  {
    path: '/login',
    name: 'Login', // 命名路由(用于 KeepAlive 缓存)
    component: Login
  },
  {
    path: '/dashboard',
    name: 'Dashboard',
    component: Dashboard,
    meta: { requiresAuth: true } // 标记:需要登录才能访问
  },
  {
    path: '/orders',
    name: 'OrderList',
    component: OrderList,
    meta: { requiresAuth: true, keepAlive: true } // 需要登录 + 缓存组件
  },
  {
    path: '/orders/:id', // 动态路由参数(订单ID)
    name: 'OrderDetail',
    component: OrderDetail,
    meta: { requiresAuth: true },
    props: true // 把路由参数映射为组件 props(可选)
  }
];

// 创建路由实例
const router = createRouter({
  history: createWebHistory(import.meta.env.BASE_URL), // HTML5 历史模式
  routes
});

// 全局注册(src/main.ts)
import { createApp } from 'vue';
import { createPinia } from 'pinia';
import App from './App.vue';
import router from './router';

const app = createApp(App);
app.use(createPinia());
app.use(router);
app.mount('#app');

2. 路由出口(App.vue)

vue

<template>
  <!-- 路由出口:渲染匹配的组件 -->
  <router-view v-slot="{ Component }">
    <!-- 缓存指定组件(结合 keepAlive 标记) -->
    <keep-alive :include="['OrderList', 'Dashboard']">
      <component :is="Component" />
    </keep-alive>
  </router-view>
</template>

3. 组件中使用路由(跳转 / 传参)

(1)基础跳转(比如登录页跳工作台)

vue

<script setup lang="ts">
import { useRouter } from 'vue-router';
import { useUserStore } from '@/stores/user';

const router = useRouter();
const userStore = useUserStore();

const handleLogin = async () => {
  await userStore.login(loginForm.value);
  // 跳转到工作台
  router.push('/dashboard');
  // 或用命名路由(推荐,避免硬编码路径)
  // router.push({ name: 'Dashboard' });
};
</script>
(2)动态路由传参(列表页跳详情页)

vue

<!-- OrderList.vue -->
<script setup lang="ts">
import { useRouter } from 'vue-router';

const router = useRouter();

// 点击订单跳详情页,传递 orderId
const handleGoDetail = (orderId: string) => {
  // 方式1:路径传参
  router.push(`/orders/${orderId}`);
  // 方式2:命名路由 + 参数(推荐)
  // router.push({ name: 'OrderDetail', params: { id: orderId } });
};
</script>
(3)详情页接收参数

vue

<!-- OrderDetail.vue -->
<script setup lang="ts">
import { useRoute } from 'vue-router';
import { onMounted } from 'vue';
import { useOrderStore } from '@/stores/order';

const route = useRoute();
const orderStore = useOrderStore();

// 方式1:直接读取路由参数
const orderId = route.params.id as string;

// 方式2:通过 props 接收(路由配置中开启 props: true)
// const props = defineProps<{ id: string }>();
// const orderId = props.id;

// 加载订单详情
onMounted(() => {
  orderStore.fetchOrderDetail(orderId);
});
</script>

三、高级实战(CRM 核心需求)

1. 路由守卫(权限控制)

CRM 最核心的路由需求是 “权限控制”(未登录禁止访问、不同角色访问不同页面),通过「全局前置守卫」实现:

typescript

运行

// src/router/index.ts
import { useUserStore } from '@/stores/user';

// 全局前置守卫:跳转前验证权限
router.beforeEach((to, from, next) => {
  const userStore = useUserStore();
  // 判断目标页面是否需要登录
  if (to.meta.requiresAuth && !userStore.isLogin) {
    // 未登录:跳登录页,并记录目标页面(登录后跳转回去)
    next({ path: '/login', query: { redirect: to.fullPath } });
  } else {
    // 已登录:判断角色权限(比如 admin 才能访问设置页)
    if (to.path === '/settings' && userStore.userInfo.role !== 'admin') {
      next('/dashboard'); // 无权限:跳工作台
    } else {
      next(); // 放行
    }
  }
});

// 登录页跳转回原目标页面(Login.vue)
const handleLogin = async () => {
  await userStore.login(loginForm.value);
  // 获取跳转前的目标页面,默认跳工作台
  const redirect = route.query.redirect as string || '/dashboard';
  router.push(redirect);
};

2. 与 Pinia + onActivated 协同(CRM 核心组合)

这是你最关心的点,结合三者实现 “缓存 + 刷新 + 数据一致”:

vue

<!-- OrderList.vue(订单列表页) -->
<script setup lang="ts">
import { ref, onMounted, onActivated } from 'vue';
import { useRoute } from 'vue-router';
import { useOrderStore } from '@/stores/order';

const route = useRoute();
const orderStore = useOrderStore();
const searchKey = ref('');

// 封装刷新逻辑
const fetchOrderList = async () => {
  // 结合路由参数(比如筛选条件)+ Pinia 请求数据
  const params = {
    searchKey: searchKey.value,
    page: route.query.page || 1 // 路由传分页参数
  };
  await orderStore.fetchOrderList(params);
};

// 第一次渲染:初始化
onMounted(() => {
  fetchOrderList();
});

// 核心:从详情页返回时,触发刷新(组件已缓存)
onActivated(() => {
  fetchOrderList();
});
</script>

3. 路由参数监听(筛选条件变化刷新)

CRM 列表页常通过路由参数传递筛选条件(比如 ?status=paid&page=1),监听参数变化刷新数据:

vue

<script setup lang="ts">
import { watch } from 'vue';
import { useRoute } from 'vue-router';

const route = useRoute();

// 监听路由参数变化(比如筛选条件、分页)
watch(
  () => route.query,
  () => {
    fetchOrderList(); // 参数变化,重新请求数据
  },
  { immediate: true } // 初始化时执行一次
);
</script>

四、核心避坑点(CRM 开发常错)

1. 动态路由参数变化,组件不刷新

比如从 /orders/1/orders/2,详情页不重新加载数据:

vue

<!-- 解决方案:监听路由参数变化 -->
watch(
  () => route.params.id,
  (newId) => {
    orderStore.fetchOrderDetail(newId); // 重新加载新订单数据
  },
  { immediate: true }
);

2. KeepAlive 缓存后,数据不刷新

解决方案:用 onActivated 替代 onMounted 做刷新逻辑(前面已讲)。

3. 路由守卫中使用 Pinia 注意点

路由守卫执行时,Pinia 可能还未初始化?→ 直接在守卫内调用 useUserStore() 即可(Pinia 支持延迟初始化)。

五、与 Pinia/onActivated 协同总结(核心逻辑)

表格

工具

核心职责

协同方式

Vue Router

页面跳转、路由传参、权限控制

1. 动态路由传参给组件(如 orderId);2. 路由参数传递筛选条件;3. 守卫控制页面访问权限

Pinia

全局数据存储、异步请求封装

1. 组件从 Pinia 读取数据;2. Action 封装请求逻辑;3. 权限判断依赖 Pinia 的用户状态

onActivated

缓存组件激活时刷新数据

1. 返回列表页时触发刷新;2. 刷新逻辑同步路由参数和 Pinia 数据

六、最终总结(CRM 开发最佳实践)

  1. 核心组合Vue Router(页面跳转/权限) + Pinia(全局数据) + onActivated(缓存刷新) 是 CRM 开发的 “铁三角”,覆盖 100% 核心场景;
  2. 路由设计原则
    • 按业务模块拆分路由(/orders//customers//dashboard);
    • 动态路由传核心参数(如订单 ID),查询参数传筛选 / 分页条件;
    • 给需要缓存的页面加 keepAlive 标记,配合 onActivated 刷新;
  1. 权限控制:通过全局前置守卫 + Pinia 的用户状态,实现 “登录验证 + 角色权限” 双层控制;
  2. Mitt 定位:仅在 “跨页面 / 跨框架通信、纯 UI 动作触发” 等极特殊场景补位,核心场景完全不用。

这个 “铁三角” 组合是 Vue3 开发 CRM 系统的最优解,既保证了代码的规范性,又兼顾了用户体验(缓存 + 按需刷新),完全贴合你 “少用冗余工具、聚焦核心逻辑” 的开发思路。

更多推荐