> 技术文档 > Vue2下

Vue2下


六:vue-router (重要)

(一). 对路由的理解

1.什么是路由


路由(Router) 是管理页面跳转和 URL 与视图映射关系的机制,核心作用是:根据不同的 URL 路径,展示对应的页面内容,实现单页应用(SPA)的页面切换

一个路由就是一组对应关系(key—value)。
key为路径,value可能是function或component。
Vue2下

核心概念:

  1. URL 与视图的映射
    路由会将 URL 路径(如 /home/about)与对应的组件(页面)关联起来,当 URL 变化时,自动渲染匹配的组件,而无需刷新整个页面(这是 SPA 的核心特性)。

  2. 单页应用(SPA)的基础
    传统多页应用通过服务器返回不同 HTML 页面实现跳转,而路由让 SPA 能在一个 HTML 页面内,通过切换组件模拟多页效果,提升用户体验(减少加载时间)。

以下是对图片内容的提取与整理,清晰区分后端路由前端路由的核心差异:

2.路由分类

2.1. 后端路由
  • 理解

    • 路由的 value函数,专门处理客户端(如浏览器)的请求。
    • 作用:服务器接收到请求后,通过路径匹配对应的处理函数,返回数据或页面。
  • 工作过程

    1. 客户端(浏览器)发送请求(如 GET /api/users)。
    2. 服务器根据请求路径,找到匹配的函数(如 Node.js 的 app.get(\'/api/users\', (req, res) => { ... }) )。
    3. 函数处理请求(查数据库、拼接数据等),返回响应(如 JSON 数据、HTML 页面)。
2.2. 前端路由
  • 理解

    • 路由的 value组件(component),用于动态展示页面内容(SPA 单页应用的核心)。
    • 作用:在浏览器端实现页面切换,无需刷新整个页面。
  • 工作过程

    1. 浏览器的 URL 路径变化(如从 /home/about)。
    2. 前端路由根据路径变化,匹配对应的组件(如 Vue 中 vue-router 的配置)。
    3. 匹配的组件渲染到页面,实现“局部更新”(无需服务器参与)。
2.3核心差异对比
对比项 后端路由 前端路由 处理位置 服务器端 浏览器端 value 类型 函数(处理请求、返回响应) 组件(展示页面内容) 页面刷新 每次请求可能刷新整个页面 仅局部更新,无整页刷新 典型技术 Node.js(Express)、Java(SpringMVC) Vue Router、React Router
2.4总结
  • 后端路由:负责“服务器如何响应请求”,用函数处理路径并返回数据/页面。
  • 前端路由:负责“浏览器如何切换内容”,用组件匹配路径并局部更新页面。

前端路由是 SPA 应用的基础,让页面跳转像“切换组件”一样丝滑~

3.前端路由的实现原理

主要依赖两种浏览器特性:

  • hash 模式:利用 URL 中的 # 后面的部分(如 http://xxx.com/#/home),hash 变化不会触发页面刷新,通过 onhashchange 事件监听变化。
  • history 模式:使用 HTML5 的 history API(如 pushStatereplaceState),可以修改 URL 且不发送请求,通过 popstate 事件监听变化。

(二).路由高级

  • 嵌套路由(children数组,配置子路由规则,对应组件内用显示 )
  • 路由守卫:全局守卫(router.beforeEach )、组件内守卫(beforeRouteEnter等 )、路由独享守卫(beforeEnter ),用于权限校验、导航控制
  • 路由懒加载(component: () => import(\'./MyRoute.vue\') ):优化首屏加载速度

1.嵌套(多级)路由

1.嵌套路由,也叫子路由,是指在一个路由组件中,还可以再嵌套其他的路由组件。在 Vue Router 中,它能够帮助构建更加复杂且层次分明的单页应用结构,让页面的组织和导航更加清晰。

应用场景

当页面存在层级关系时,适合使用嵌套路由。比如电商网站中,商品详情页是一个大的页面,在商品详情页中,又可以有商品介绍、用户评价、相关推荐等子页面,这些子页面就可以通过嵌套路由来实现。

配置步骤(以 Vue Router 在 Vue 项目中的使用为例)
1. 定义路由配置

router/index.js 文件中(假设这是路由配置文件),进行如下配置:

import Vue from \'vue\'import VueRouter from \'vue-router\'import ParentComponent from \'../components/ParentComponent.vue\'import ChildComponent1 from \'../components/ChildComponent1.vue\'import ChildComponent2 from \'../components/ChildComponent2.vue\'Vue.use(VueRouter)const routes = [ { path: \'/parent\', component: ParentComponent, children: [ { path: \'child1\', component: ChildComponent1 }, { path: \'child2\', component: ChildComponent2 } ] }]const router = new VueRouter({ routes})export default router

在上述代码中,定义了一个父路由 \'/parent\',其对应的组件是 ParentComponent。在 children 数组中,又定义了两个子路由 \'child1\'\'child2\',分别对应 ChildComponent1ChildComponent2

2. 父组件中设置路由出口

ParentComponent.vue 中,需要设置 来显示子路由对应的组件:

 

这是父组件

子组件1 子组件2

这里通过 创建了导航链接,点击链接时,会在 中显示对应的子路由组件。

访问嵌套路由

当访问 http://localhost:8080/parent/child1 时,会显示 ParentComponent 的内容,同时在 中渲染 ChildComponent1 的内容;访问 http://localhost:8080/parent/child2 时,则渲染 ChildComponent2 的内容。

嵌套路由的注意事项
  • 子路由路径:子路由的路径不要加 / 开头,否则会被当作根路径。
  • 嵌套层级:可以根据实际需求进行多层嵌套,但层级过深可能会使代码复杂度增加,维护起来更困难。
  • 路由匹配规则:当访问父路由时,如果没有匹配到具体的子路由, 中不会渲染任何内容,有时需要设置一个默认子路由来避免这种情况,比如:
{ path: \'/parent\', component: ParentComponent, children: [ { path: \'\', // 空字符串表示默认子路由 component: ChildComponent1 }, { path: \'child1\', component: ChildComponent1 }, { path: \'child2\', component: ChildComponent2 } ]}

这样,当访问 /parent 时,会默认显示 ChildComponent1 的内容。

通过嵌套路由,可以让单页应用的页面结构更加清晰合理,提升用户体验和代码的可维护性。

2.路由守卫

在 Vue Router 中,路由守卫是一种非常强大的功能,用于在路由跳转的不同阶段对导航进行拦截和控制,例如进行权限验证、记录日志、动态修改路由等。路由守卫主要分为全局守卫路由独享守卫组件内守卫三类。以下是详细介绍:

2.1全局守卫

全局守卫会对应用中所有的路由跳转起作用,主要包括以下三种:

  • router.beforeEach
    • 触发时机:在路由跳转之前,每次路由切换都会触发,并且是全局前置守卫,可以对即将发生的导航进行拦截。
    • 参数:接收三个参数,分别是to(即将要进入的目标路由对象)、from(当前导航正要离开的路由对象)、next(一个函数,必须调用它来resolve这个钩子。执行顺序决定了路由是否继续跳转 )。
    • 示例
const router = new VueRouter({...})router.beforeEach((to, from, next) => { // 模拟权限验证,假设用户登录后才有权限访问除登录页外的其他页面 const isLoggedIn = localStorage.getItem(\'token\'); if (to.path!== \'/login\' &&!isLoggedIn) { next(\'/login\'); // 未登录则重定向到登录页 } else { next(); // 允许访问,继续跳转 }})
  • router.beforeResolve
    • 触发时机:在导航被确认之前,在所有组件内守卫和异步路由组件被解析之后,beforeEach 之后触发。主要用于确保在导航确认之前,所有异步操作都已经完成。
    • 参数:和beforeEach 一样,包含tofromnext
    • 示例
router.beforeResolve((to, from, next) => { if (to.meta.requiresAsyncData) { // 假设这里有一个异步获取数据的函数 fetchAsyncData(to.params.id).then(() => { next(); }).catch(() => { next(false); }); } else { next(); }});
  • router.afterEach
    • 触发时机:在路由跳转完成之后触发,没有next 函数,不能对导航进行拦截,主要用于进行一些不需要对导航进行干预的操作,比如记录页面访问日志。
    • 参数:接收两个参数,分别是to(成功跳转的目标路由对象)、from(离开的路由对象)。
    • 示例
router.afterEach((to, from) => { console.log(`${from.path} 跳转到了 ${to.path}`); // 可以在这里调用接口记录页面访问日志等操作})

在 Vue Router 中,全局守卫是作用于整个应用所有路由的导航钩子,用于统一处理路由跳转的权限验证、日志记录、数据预处理等逻辑。全局守卫分为三类,分别在路由跳转的不同阶段触发,以下是详细解析:

一、全局前置守卫(beforeEach
作用

路由跳转前触发,是全局守卫中最常用的一种,主要用于拦截导航、验证权限、重定向等操作。

触发时机
  • 每次路由切换(包括初始化时的首次加载)都会触发。
  • 执行顺序:在所有组件内守卫和路由独享守卫之前。
参数
  • to:即将进入的目标路由对象(包含路径、参数、元信息等)。
  • from:当前正要离开的路由对象。
  • next:函数,必须调用以决定导航行为:
    • next():允许导航继续。
    • next(false):取消导航,停留在当前页面。
    • next(\'/path\')next({ name: \'routeName\' }):重定向到指定路由。
    • next(error):传递错误对象,会被全局错误处理器捕获。
示例(权限验证)
const router = new VueRouter({... })// 全局前置守卫:验证用户是否登录router.beforeEach((to, from, next) => { // 1. 登录页无需验证,直接放行 if (to.path === \'/login\') { next(); return; } // 2. 非登录页:检查是否有登录凭证(如 token) const token = localStorage.getItem(\'token\'); if (token) { // 已登录:允许进入目标路由 next(); } else { // 未登录:强制重定向到登录页 next(\'/login\'); }});
二、全局解析守卫(beforeResolve
作用

导航被确认前触发,用于确保所有异步操作(如组件加载、数据请求)完成后再进入目标路由。

触发时机
  • beforeEach 之后,afterEach 之前。
  • 会等待所有组件内守卫和异步路由组件解析完成后才执行。
参数

beforeEach 相同(tofromnext)。

示例(预处理数据)
// 全局解析守卫:确保数据加载完成router.beforeResolve(async (to, from, next) => { // 如果路由需要预加载数据(通过 meta 标记) if (to.meta.needPreload) { try { // 异步加载数据 await fetchData(to.params.id); next(); // 数据加载完成,允许导航 } catch (error) { next(\'/error\'); // 加载失败,重定向到错误页 } } else { next(); // 无需预加载,直接放行 }});
三、全局后置钩子(afterEach
作用

路由跳转完成后触发,主要用于执行不需要干预导航的操作(如日志记录、页面滚动)。

触发时机
  • 导航已完成,目标组件已渲染。
  • next 函数,无法拦截或修改导航
参数
  • to:成功进入的目标路由对象。
  • from:离开的路由对象。
示例(记录访问日志)
// 全局后置钩子:记录页面访问日志router.afterEach((to, from) => { // 1. 打印跳转信息 console.log(`${from.path} 跳转到 ${to.path}`); // 2. 调用接口记录日志(实际项目中使用 axios 等工具) fetch(\'/api/log\', { method: \'POST\', body: JSON.stringify({ fromPath: from.path, toPath: to.path, time: new Date().toISOString() }) }); // 3. 页面滚动到顶部 window.scrollTo(0, 0);});
四、全局守卫的执行顺序
  1. 触发路由跳转 → beforeEach(全局前置)
  2. 加载异步路由组件(若有)
  3. 执行目标路由的路由独享守卫(beforeEnter
  4. 执行目标组件内的 beforeRouteEnter 守卫
  5. 所有异步操作完成 → beforeResolve(全局解析)
  6. 导航确认,组件渲染 → afterEach(全局后置)
五、核心使用场景
  • beforeEach:权限验证、登录拦截、动态路由生成。
  • beforeResolve:路由跳转前的异步数据预处理。
  • afterEach:页面访问日志、滚动位置重置、埋点统计。
六、注意事项
  1. 避免无限循环:在 beforeEach 中重定向时,需确保条件判断正确(如登录页不重定向自身)。
  2. 异步操作处理:若有异步逻辑(如接口请求),需用 async/await 包裹,并在完成后调用 next()
  3. 性能影响:全局守卫会拦截所有路由跳转,复杂逻辑可能影响性能,建议保持简洁。

全局守卫是 Vue Router 中实现统一导航控制的核心工具,通过合理组合三类守卫,可实现从权限验证到数据处理的全流程管控。


2.2路由独享守卫

可以为某个特定的路由配置守卫,只对该路由生效。

  • beforeEnter
    • 触发时机:在进入对应的路由之前触发。
    • 参数:接收三个参数,分别是to(即将要进入的目标路由对象)、from(当前导航正要离开的路由对象)、next(和全局守卫中的next 函数作用相同)。
    • 示例
const router = new VueRouter({ routes: [ { path: \'/admin\', component: Admin, beforeEnter: (to, from, next) => { // 只有管理员角色才能访问 const userRole = localStorage.getItem(\'role\'); if (userRole === \'admin\') { next(); } else { next(\'/forbidden\'); // 无权限则重定向到禁止访问页面 } } } ]})

在 Vue Router 中,路由独享守卫是一种仅作用于特定路由配置的导航钩子,允许你在某个路由跳转前进行定制化拦截和处理,而不必影响其他路由。以下是其核心用法与场景:

一、核心语法(beforeEnter
const router = new VueRouter({ routes: [ { path: \'/admin\', component: AdminPanel, beforeEnter: (to, from, next) => { // 路由独享守卫逻辑 if (!isAdmin) { next(\'/login\'); // 无权限则重定向 } else { next(); // 允许访问 } } } ]});
二、参数与执行流程
1. 参数
  • to:目标路由对象(包含路径、参数、元信息等)。
  • from:当前路由对象。
  • next:控制导航行为的函数(同全局守卫的 next)。
2. 执行时机
  • 在全局前置守卫(beforeEach)之后,组件内守卫(beforeRouteEnter)之前执行。
  • 仅在进入该路由时触发,离开时不触发。
三、典型应用场景
1. 权限控制(如管理员页面)
{ path: \'/admin\', component: AdminPanel, beforeEnter: (to, from, next) => { const userRole = localStorage.getItem(\'role\'); if (userRole === \'admin\') { next(); // 管理员允许访问 } else { next(\'/forbidden\'); // 非管理员跳转至禁止页 } }}
2. 数据预处理
{ path: \'/profile/:id\', component: UserProfile, beforeEnter: async (to, from, next) => { try { // 预加载用户数据 const user = await fetchUser(to.params.id); // 将数据存入路由元信息,供组件使用 to.meta.user = user; next(); } catch (error) { next(\'/404\'); // 加载失败跳转 404 } }}
3. 导航条件判断
{ path: \'/payment\', component: PaymentPage, beforeEnter: (to, from, next) => { // 检查购物车是否有商品 const hasItems = localStorage.getItem(\'cartItems\'); if (hasItems) { next(); } else { next(\'/cart\'); // 无商品则跳转购物车 } }}
四、与其他守卫的对比
守卫类型 作用范围 触发时机 适用场景 全局前置守卫 所有路由 路由跳转前 统一权限验证、登录拦截 路由独享守卫 单个路由配置 进入特定路由前 特定页面的权限控制、数据预加载 组件内守卫 组件内部 组件实例相关的导航阶段 组件级别的导航逻辑
五、注意事项
  1. 只作用于直接匹配的路由
    如果路由配置了子路由,beforeEnter 仅在进入该路由时触发,不会作用于子路由。

  2. 避免重复逻辑
    若多个路由需要相同的守卫逻辑,建议使用全局守卫或高阶函数封装,减少代码冗余。

  3. 异步操作处理
    若守卫中包含异步请求(如验证 Token),需使用 async/await 确保数据加载完成后再调用 next()

六、总结

路由独享守卫是 Vue Router 中实现细粒度导航控制的灵活工具,适合在不影响全局导航的前提下,对特定路由添加定制化的拦截逻辑。合理使用它可提升代码的可维护性,避免全局守卫过于臃肿。


2.3组件内守卫

在路由组件内部定义的守卫,只在当前组件对应的路由跳转时生效。

  • beforeRouteEnter
    • 触发时机:在路由进入该组件之前触发,此时组件实例还未被创建,所以不能访问this
    • 参数:接收三个参数,分别是to(即将要进入的目标路由对象)、from(当前导航正要离开的路由对象)、nextnext 函数可以接收一个回调函数,在组件实例创建好之后执行 )。
    • 示例
export default { beforeRouteEnter(to, from, next) { // 模拟获取数据后再进入组件 getData().then(data => { next(vm => { vm.$data.data = data; // vm 是组件实例 }); }).catch(() => { next(false); }); }}
  • beforeRouteUpdate
    • 触发时机:在当前路由改变,但是该组件被复用时调用,比如在带有动态参数的路由中,当参数变化时,组件会被复用,此时会触发该守卫。
    • 参数:接收三个参数,分别是to(即将要进入的目标路由对象)、from(当前导航正要离开的路由对象)、next(和其他守卫中的next 函数作用相同)。
    • 示例
export default { beforeRouteUpdate(to, from, next) { // 当路由参数变化时,重新获取数据 if (to.params.id!== from.params.id) { this.fetchNewData(to.params.id); } next(); }}
  • beforeRouteLeave
    • 触发时机:在导航离开该组件时触发,可用于询问用户是否确认离开,比如用户在表单中输入了内容还未保存时。
    • 参数:接收三个参数,分别是to(即将要进入的目标路由对象)、from(当前导航正要离开的路由对象)、next(和其他守卫中的next 函数作用相同)。
    • 示例
export default { beforeRouteLeave(to, from, next) { if (this.hasUnsavedChanges) { const confirmLeave = window.confirm(\'你有未保存的更改,确定要离开吗?\'); if (confirmLeave) { next(); } else { next(false); } } else { next(); } }}

通过合理运用这些路由守卫,可以实现丰富且强大的导航控制逻辑,提升应用的安全性和用户体验。

在 Vue Router 中,组件内守卫是直接定义在路由组件内部的导航钩子,用于控制该组件实例相关的路由导航行为。与全局守卫和路由独享守卫不同,组件内守卫仅作用于当前组件,提供更精细的导航控制。以下是其核心用法与场景:

一、三种组件内守卫
1. beforeRouteEnter
  • 触发时机:在路由进入组件前触发,此时组件实例尚未创建,因此无法访问 this
  • 用途:可通过 next 回调访问组件实例,常用于在路由进入前预加载数据。
  • 示例
    export default { beforeRouteEnter(to, from, next) { // 异步获取数据(如用户信息) fetchUser(to.params.id).then(user => { // 通过 next 回调访问组件实例 next(vm => { vm.user = user; // 将数据传递给组件实例 }); }); }}
2. beforeRouteUpdate
  • 触发时机:在当前路由改变(如参数变化)但组件被复用时触发,此时组件实例已存在,可访问 this
  • 用途:常用于动态参数路由(如 /user/:id)的更新逻辑,避免组件重复创建。
  • 示例
    export default { watch: { // 传统方式:监听 $route 变化 $route(to) { this.fetchData(to.params.id); } }, // 更优解:使用组件内守卫 beforeRouteUpdate(to, from, next) { // 参数变化时重新加载数据 if (to.params.id !== from.params.id) { this.fetchData(to.params.id); } next(); }}
3. beforeRouteLeave
  • 触发时机:在导航离开当前组件时触发,可访问 this
  • 用途:常用于阻止用户意外离开(如未保存表单),或清理资源。
  • 示例
    export default { data() { return { formDirty: false // 表单是否已修改 }; }, beforeRouteLeave(to, from, next) { if (this.formDirty) { const confirmLeave = window.confirm(\'表单尚未保存,确定离开?\'); confirmLeave ? next() : next(false); // 确认后允许离开 } else { next(); // 未修改直接放行 } }}
二、组件内守卫的执行顺序

当路由发生变化时,守卫的触发顺序为:

  1. 全局beforeEach
  2. 路由独享beforeEnter
  3. 组件内
    • 当前组件的 beforeRouteLeave(若离开当前组件)
    • 目标组件的 beforeRouteEnter(若进入新组件)
  4. 全局beforeResolve
  5. 全局afterEach
三、典型应用场景
1. 数据预加载
export default { beforeRouteEnter(to, from, next) { // 进入组件前预加载文章数据 fetchArticle(to.params.id).then(article => { next(vm => { vm.article = article; }); }); }}
2. 动态路由参数更新
export default { beforeRouteUpdate(to, from, next) { // 当路由参数变化时(如从 /user/1 到 /user/2) this.fetchUser(to.params.id); next(); }}
3. 防止数据丢失
export default { beforeRouteLeave(to, from, next) { // 检查是否有未保存的草稿 if (this.hasDraft) { saveDraft().then(() => next()); } else { next(); } }}
四、与其他守卫的对比
守卫类型 定义位置 能否访问 this 适用场景 全局守卫 路由配置文件 否 全局权限验证、日志记录 路由独享守卫 路由配置对象 否 特定路由的权限控制 组件内守卫 组件内部 beforeRouteEnter 不可,其他可 组件级的导航逻辑、数据预加载
五、注意事项
  1. beforeRouteEnter 中访问组件实例
    由于此时组件尚未创建,需通过 next(vm => { ... }) 回调访问实例。

  2. 避免重复逻辑
    若多个组件需要相同的守卫逻辑,可使用 mixin 或全局守卫减少代码冗余。

  3. 异步操作处理
    若守卫中包含异步请求(如验证 Token),需确保数据加载完成后再调用 next()

六、总结

组件内守卫是 Vue Router 中实现组件级导航控制的强大工具,通过 beforeRouteEnterbeforeRouteUpdatebeforeRouteLeave 三个钩子,可精确控制组件实例的导航生命周期。合理使用组件内守卫能提升用户体验(如防止数据丢失),并优化组件性能(如复用组件时的数据更新)。


3.history模式与hash模式

在 Vue Router 中,history 模式和**hash 模式**是两种不同的路由实现方式,主要区别在于 URL 的表现形式和浏览器历史记录的处理方式。以下是详细对比与选择建议:

Vue2下

一、核心区别
特性 hash 模式(默认) history 模式 URL 格式 http://example.com/#/home http://example.com/home 路径标识符 使用 # 符号分隔路径(如 #/user/1) 直接使用真实路径(如 /user/1历史记录 hash 变化会触发浏览器历史记录,但不会向服务器发送请求 依赖 HTML5 History API(pushState/replaceState),路径变化会被记录到历史中 服务器配置 无需特殊配置,所有请求都指向根页面 需要服务器配置,确保所有路由请求都返回同一个 HTML 文件 兼容性 支持所有浏览器(包括 IE9+) 依赖 HTML5 History API,IE9 及以下不支持
二、hash 模式详解
  1. 工作原理
  • URL 中的 # 及其后的内容被视为浏览器的 hash 值,不会被发送到服务器。
  • hash 变化时(如 #/home#/about),Vue Router 会拦截并根据 hash 值渲染对应组件。
  1. 优点
  • 无需服务器配置:所有请求都指向根页面(如 index.html),适合快速开发和静态网站。
  • 兼容性强:支持所有现代浏览器,甚至包括 IE9。
  1. 缺点
  • URL 不美观# 符号在 URL 中较为突兀,不符合传统 URL 格式。
  • SEO 不友好:搜索引擎爬虫通常会忽略 hash 值,不利于页面收录。
三、history 模式详解
  1. 工作原理
  • 使用 HTML5 的 pushStatereplaceState API 操作浏览器历史记录,URL 看起来像传统的静态页面路径(如 /home)。
  • 当用户访问 /user/1 时,浏览器会向服务器发送请求,但实际上所有路径都应返回同一个 HTML 文件(如 index.html),由 Vue Router 在客户端处理路由逻辑。
  1. 优点
  • URL 更优雅:没有 # 符号,符合传统 URL 格式,提升用户体验。
  • SEO 友好:搜索引擎可以直接抓取真实路径,有利于页面收录。
  1. 缺点
  • 服务器配置复杂:需要服务器配置所有路由请求都返回 index.html,否则会出现 404 错误(见下方服务器配置示例)。
  • 兼容性较差:不支持 IE9 及以下浏览器。
四、服务器配置示例(history 模式)
  1. Node.js (Express)
const express = require(\'express\');const app = express();// 静态文件处理app.use(express.static(__dirname + \'/dist\'));// 所有路由请求都返回 index.htmlapp.get(\'*\', function(req, res) { res.sendFile(__dirname + \'/dist/index.html\');});app.listen(8080);
五、如何选择?
  • 优先使用 history 模式
    如果项目需要良好的 SEO、更优雅的 URL,且不考虑 IE9 及以下浏览器,推荐使用 history 模式。

  • 使用 hash 模式的场景

    • 项目不需要 SEO(如内部管理系统)。
    • 无法配置服务器(如 GitHub Pages、静态网站托管)。
    • 需要兼容 IE9 及以下浏览器。
六、切换模式的方法

在 Vue Router 配置中,通过 mode 选项指定模式:

const router = new VueRouter({ mode: \'history\', // 启用 history 模式(默认是 hash 模式) routes: [...]});
七、总结
场景 hash 模式 history 模式 静态网站/快速开发 ✅ ❌(需服务器配置) 企业内部系统 ✅(兼容性好) ✅(URL 更优雅) 电商/内容网站(需 SEO) ❌ ✅ 兼容性要求 ✅(支持 IE9+) ❌(不支持 IE9 及以下)

选择时需权衡 URL 美观性、SEO 需求、服务器配置复杂度和浏览器兼容性。history 模式是现代 Web 应用的首选,但需要服务器配合;hash 模式则适用于快速迭代和兼容性要求高的场景。


(三)、vue-router(路由管理)

vue的一个插件库,专门用来实现SPA应用

1.安装与配置

使用npm install vue-router@3安装,然后在项目中进行配置。
使用:Vue.use(Router);

// router/index.jsimport Vue from \'vue\';import Router from \'vue-router\';import Home from \'../views/Home.vue\';import About from \'../views/About.vue\';Vue.use(Router);export default new Router({ // 路由模式,可选\'hash\'(默认,URL中包含#)和\'history\'(更美观的URL) mode: \'history\', routes: [ { // 路由路径 path: \'/\', // 路由名称 name: \'Home\', // 对应的组件 component: Home }, { path: \'/about\', name: \'About\', component: About } ]});

main.js中引入并使用路由:

import Vue from \'vue\';import App from \'./App.vue\';import router from \'./router\';new Vue({ router, render: h => h(App)}).$mount(\'#app\');

2.路由导航与参数

  1. 导航:使用组件进行路由导航。
<router-link to=\"/\">Home</router-link><router-link to=\"/about\">About</router-link>
  1. 动态路由参数:在路由路径中使用参数,如/user/:id,可以在组件中通过$route.params获取参数值。
// User.vueexport default { created() { const userId = this.$route.params.id; console.log(\'用户ID:\', userId); }};

(四)对SPA应用的理解

  1. 定义:单页 Web 应用(single page web application,SPA )
  2. 页面特征:整个应用只有一个完整的页面
  3. 交互特点:点击页面中的导航链接不会刷新页面,只会做页面的局部更新
  4. 数据获取:数据需要通过 ajax 请求获取

(五)基本路由

注意:

  1. 存储位置
    • 路由组件:通常存放在 pages 文件夹
    • 一般组件:通常存放在 components 文件夹
  2. 路由组件销毁与挂载:通过切换,“隐藏”了的路由组件,默认是被销毁掉的,需要的时候再去挂载
  3. 组件路由信息属性:每个组件都有自己的 $route 属性,里面存储着自己的路由信息
  4. 全局路由实例获取:整个应用只有一个 router,可以通过组件的 $router 属性获取到 。

路由传参

query参数(静态)

Vue2下
Vue2下

命名路由
一、命名路由的作用

简化路由跳转:无需硬编码完整路径,通过路由名称(name)实现跳转,避免路径变更时大量修改代码。

二、使用步骤
1. 给路由“命名”(配置阶段)

在路由配置中,为目标路由添加 name 属性:

const routes = [ { path: \'/demo\', component: Demo, children: [ { path: \'test\', component: Test, children: [ { name: \'hello\', // 给路由命名(关键) path: \'welcome\', component: Hello } ] } ] }]
2. 简化跳转(组件中使用)

未简化前:需写完整路径,易出错且难维护:

<router-link to=\"/demo/test/welcome\">跳转</router-link>

简化后:通过 name 跳转,路径变化时只需改配置:

<router-link :to=\"{ name: \'hello\' }\">跳转</router-link>

简化写法:命名路由 + query 参数

<router-link :to=\"{ name: \'hello\', // 路由名称(对应路由配置的 name: \'hello\') query: { // 传递 query 参数(会显示在 URL 中,如 ?id=666&title=你好) id: 666, title: \'你好\' } }\"> 跳转并传参</router-link>
三、核心优势
  • 解耦路径与跳转:路由名称不变时,即使路径(如 /demo/test/welcome)修改,跳转代码无需改动。
  • 支持动态参数:结合 params/query 传参更灵活(如 :to=\"{ name: \'hello\', params: { id: 1 } }\" )。
总结

命名路由是给路由起一个“别名”(name),让跳转从“写死路径”变成“调用名称”,核心价值是简化跳转逻辑、提升可维护性

路由的params参数(动态)
1.配置路由,声明接收 params 参数

配置路由以接收 params 参数,通过 占位符(:id:title 定义动态路径,让组件能接收 URL
中的动态参数。

1.1. 路由配置(核心片段)
{ path: \'/home\', component: Home, children: [ { component: Message, children: [ { name: \'xiangqing\',  path: \'detail/:id/:title\', // 占位符声明 params 参数 component: Detail } ] } ]}

代码解析:

  • path: \'detail/:id/:title\'
    • :id:title 占位符,声明该路由需要接收 idtitle 两个 params 参数。
    • 访问时路径如 /home/message/detail/1/xxx,其中 1xxx 会作为 params 传递。

流程说明 :

  1. 路由定义
    通过 path: \'detail/:id/:title\' 告诉 Vue Router:

    • 该路径是动态的,idtitle 是可变参数。
    • 这些参数会以 params 形式传递给 Detail 组件。
  2. 参数传递与接收

    • 跳转时需通过 params 传入数据(如 this.$router.push({ name: \'xiangqing\', params: { id: 1, title: \'xxx\' } }) )。
    • Detail 组件中通过 this.$route.params.idthis.$route.params.title 接收参数。

核心特点

  • 动态路径:URL 中的 idtitle 是动态的,不同参数对应不同页面状态。
  • 强关联路由params 参数必须与路由配置的占位符一一对应,否则路由无法匹配。
1.2对比 query 参数
对比项 params 参数 query 参数 路径形式 /detail/1/xxx(参数嵌入路径) /detail?id=1&title=xxx(参数跟在 ? 后) 路由配置 需用 :占位符 声明 无需特殊配置 参数是否必填 是(否则路由不匹配) 否(可传可不传)
1.3 注意事项
  1. 参数必填性
    由于 params 参数通过占位符声明,跳转时必须传入对应参数,否则路由无法匹配(如少传 title 会导致 404)。

  2. 命名路由配合
    建议结合 name: \'xiangqing\' 使用,跳转时代码更简洁:

    this.$router.push({ name: \'xiangqing\', params: { id: 1, title: \'xxx\' } })
  3. 组件接收参数
    Detail 组件中,通过 this.$route.params 而非 props 接收(除非开启 props: true 配置)。

这是 Vue Router 中 动态路由传参 的基础用法,核心是通过 占位符 让 URL 携带动态数据,常用于商品详情、文章详情等场景~

2.params 参数的传递方式:
1. 字符串写法(直接拼接路径)
<router-link to=\"/home/message/detail/666/你好\">跳转</router-link>
  • 特点
    • 直接拼接 params 到 URL(666id你好title)。
    • 需严格按照路由配置的 path: \'detail/:id/:title\' 格式拼接,易出错。
2. 对象写法(推荐)
<router-link :to=\"{ name: \'xiangqing\', params: { id: 666, title: \'你好\' } }\"> 跳转</router-link>
  • 关键规则
    • 必须用 name: \'xiangqing\'(路由的命名),不能用 path
    • 通过 params 字段传递参数,Vue Router 会自动拼接成动态路径。
注意事项

对象写法的强制规则

  • 当用对象传递 params 时,必须通过 name 匹配路由,而不能用 path
  • 原因:path 是静态的,无法动态拼接 paramsname 与路由配置的 name: \'xiangqing\' 关联,能正确解析 params
两种写法对比
写法 优点 缺点 适用场景 字符串写法 简单直观 易因路径变化(如参数顺序)出错 简单场景,参数少且固定 对象写法 解耦路径与参数,更健壮 需定义路由 name 复杂场景,参数多或动态变化
核心结论

传递 params 参数时:

  • 若用 对象写法,必须配合 name(不能用 path),这是 Vue Router 的强制规则。
  • 推荐优先用 对象写法,避免路径拼接错误,且更易维护(路由名称不变时,路径变化不影响跳转)。

这是 Vue Router 中 params 参数传递的核心细节,记住 “对象写法必须用 name” 即可避免常见错误~

3. 接收 params 参数:

在组件中获取路由传递的 params 参数(如 idtitle),用于渲染动态内容(如商品详情、文章标题)。

1.关键代码
// 组件中接收 params 参数const id = this.$route.params.idconst title = this.$route.params.title
2.流程说明
  1. 路由传递 params
    通过 router-linkthis.$router.push 传递 params(如 { params: { id: 666, title: \'你好\' } } )。

  2. 组件接收参数
    Vue Router 会将 params 挂载到 this.$route.params 中,组件直接访问 this.$route.params.idthis.$route.params.title 即可。

3.与 query 参数的区别
参数类型 存储位置 组件中获取方式 特点 params 动态路径(如 /detail/666/你好this.$route.params.xxx 参数隐藏在路径中,更“干净” query URL 查询字符串(如 ?id=666this.$route.query.xxx 参数显示在 URL 中,可分享
4.注意事项
  1. 路由配置依赖
    必须在路由中通过 path: \'detail/:id/:title\' 声明 params 占位符,否则 this.$route.params 无法获取参数。

  2. 组件更新问题
    如果组件复用(如不同 id 但同一路由),需通过 watch 监听 $route.params 变化:

    watch: { \'$route.params\'() { // 参数变化时重新加载数据 this.fetchData(this.$route.params.id); }}
5.总结

接收 params 参数的核心是通过 this.$route.params.xxx,需注意路由配置的占位符声明,以及组件复用场景下的参数监听。这是 Vue Router 动态路由传参的基础用法,常用于商品详情、文章详情等场景。


路由的props配置

在 Vue Router 中,props 配置是一种将路由参数(如 paramsquery)直接映射为组件 props 的机制,目的是解耦组件与路由,让组件更易于测试和复用。以下是其核心用法与场景:

一、基础用法(三种模式)
1. 布尔模式(最常用)
  • 配置props: true
  • 效果:将 params 参数转为组件 propsquery 不处理。
  • 示例
    // 路由配置{ path: \'/user/:id\', component: User, props: true // 开启 props 模式}// User 组件export default { props: [\'id\'], // 直接接收路由 params 参数 mounted() { console.log(this.id); // 访问路由参数 }}
2. 对象模式
  • 配置props: { key: value }
  • 效果:传递固定的静态数据给组件,不依赖路由参数。
  • 示例
    { path: \'/about\', component: About, props: { title: \'关于我们\', version: \'1.0.0\' } // 传递静态数据}
3. 函数模式(最灵活)
  • 配置props: (route) => ({...})
  • 效果:通过函数动态生成 props,可处理 paramsquery 或其他逻辑。
  • 示例
    { path: \'/search\', component: Search, props: (route) => ({ keyword: route.query.q, // 从 query 获取参数 page: parseInt(route.query.page) || 1 // 处理默认值 })}

汇总:

{ name:\'xiangqing\', path:\'detail/:id\', component:Detail, //第一种写法:props值为对象,该对象中所有的key - value的组合最终都会通过props传给Detail组件 // props:{a:900} //第二种写法:props值为布尔值,布尔值为true,则把路由收到的所有params参数通过props传给Detail组件 // props:true //第三种写法:props值为函数,该函数返回的对象中每一组key - value都会通过props传给Detail组件 props(route){ return { id:route.query.id, title:route.query.title }
二、核心优势
  1. 组件复用性提升
    组件不再依赖 this.$route,可独立使用(如在非路由场景下复用)。

    // 无 props 配置时,组件依赖路由console.log(this.$route.params.id); // 耦合路由// 有 props 配置时,组件只关心 propsconsole.log(this.id); // 解耦路由,可独立测试
  2. 测试更简单
    测试组件时,可直接传入 props,无需模拟路由环境。

    // 测试代码示例const wrapper = shallowMount(User, { propsData: { id: \'123\' } // 直接传入 props});
  3. 代码更清晰
    组件 props 声明明确,一眼看出依赖哪些参数。

三、对比直接访问 $route
方式 优点 缺点 适用场景 直接用 $route 简单直接,无需额外配置 组件与路由强耦合 小型项目、快速开发 props 配置 解耦路由,组件可复用 需要额外配置 中大型项目、组件复用多
四、注意事项
  1. 仅处理 params
    props: true 时,只有 params 参数会被转为 propsquery 参数需通过函数模式手动处理。

  2. 与命名路由配合
    传递 params 时,建议用命名路由(如 name: \'user\'),避免路径拼接错误。

    <router-link :to=\"{ name: \'user\', params: { id: 1 } }\">用户详情</router-link>
  3. 函数模式的性能
    函数模式每次路由变化都会执行,避免在函数中做复杂计算,可通过 computed 缓存结果。

五、典型场景
  • 商品详情页:通过 id 获取商品数据。

    { path: \'/product/:id\', component: ProductDetail, props: true}
  • 搜索结果页:通过 query 参数获取搜索关键词。

    { path: \'/search\', component: SearchResult, props: (route) => ({ keyword: route.query.q })}
  • 静态页面:传递固定数据(如标题、配置)。

    { path: \'/help\', component: HelpPage, props: { title: \'帮助中心\' }}
总结

props 配置是 Vue Router 中解耦组件与路由的关键机制,通过三种模式(布尔、对象、函数)将路由参数转为组件 props,让组件更独立、可测试、易复用。建议在中大型项目中优先使用,提升代码质量。

router-link的replace属性

在 Vue Router 中,router-link 是用于生成导航链接的组件,它的 replace 属性主要用于控制导航行为,以下是关于它的详细介绍:
以下是提取的文字内容:

replace属性

  1. 作用:控制路由跳转时操作浏览器历史记录的模式
  2. 浏览器的历史记录有两种写入方式:分别为pushreplacepush是追加历史记录,replace是替换当前记录。路由跳转时候默认为push
  3. 如何开启replace模式:News
1. 基本作用

replace 属性的作用是用新的历史记录条目替换当前的历史记录条目,而不是向历史记录栈中添加一个新条目。

在普通情况下,当我们使用 进行页面跳转时,每次跳转都会在浏览器的历史记录中新增一条记录,用户可以通过点击浏览器的“后退”按钮回到上一个页面。但是当给 添加了 replace 属性后,跳转时会替换当前的历史记录,此时浏览器的“后退”按钮将无法退回到跳转前的页面 。

2. 使用方式

组件中,直接添加 replace 属性即可,它不需要绑定具体的值,类似于 HTML 中的布尔属性,只要存在该属性,就会生效。示例代码如下:

<template> <div>  <router-link to=\"/home\">前往首页</router-link>  <router-link to=\"/about\" replace>前往关于页面</router-link> </div></template>

上述代码中,点击“前往首页”的链接时,浏览器历史记录会新增一条记录;而点击“前往关于页面”的链接时,当前的历史记录会被替换。

3. 应用场景
  • 防止用户返回:在一些场景下,比如用户进行了不可逆的操作(如提交表单、支付成功后),不希望用户通过点击“后退”按钮回到之前的页面,此时可以使用 replace 属性。例如,在电商网站中,当用户完成支付后跳转到支付成功页面,为了避免用户误点“后退”按钮回到支付页面造成混乱,可以在支付成功页面的跳转链接中添加 replace 属性。
<router-link to=\"/payment-success\" replace>支付成功</router-link>
  • 简化历史记录:当页面的导航逻辑比较复杂,且某些跳转不需要用户回溯时,使用 replace 属性可以让浏览器的历史记录更加简洁明了,避免历史记录中出现过多不必要的条目 。
4. 与编程式导航的对比

除了通过 replace 属性控制导航行为外,编程式导航(this.$router.pushthis.$router.replace)也能实现类似功能。

  • this.$router.push:向历史记录栈中添加一个新条目,与普通的 效果类似。
  • this.$router.replace:用新的条目替换当前历史记录条目,类似于 加上 replace 属性。

示例代码:

export default { methods: { goToPage() { // 普通push,增加历史记录 this.$router.push(\'/some-page\'); // 使用replace,替换历史记录 this.$router.replace(\'/another-page\'); } }}

总之,router-linkreplace 属性为我们在 Vue Router 中控制导航的历史记录行为提供了一种便捷的方式,合理使用它可以优化用户体验和页面导航逻辑。

编程式路由导航

在 Vue Router 中,除了使用 声明式创建导航链接外,还可以通过 编程式路由导航 实现更灵活的路由跳转。这种方式通过 JavaScript 代码触发路由变化,适用于条件跳转、事件回调等场景。

Vue2下

一、核心 API
1. this.$router.push(location)
  • 作用:向历史记录栈中添加一个新条目,等同于
  • 参数:可以是字符串路径或描述目标位置的对象。
  • 示例
    // 字符串路径this.$router.push(\'/home\');// 对象路径(命名路由 + params)this.$router.push({ name: \'user\', params: { id: 123 } });// 对象路径(带 query 参数)this.$router.push({ path: \'/search\', query: { keyword: \'vue\' } });
2. this.$router.replace(location)
  • 作用:替换当前历史记录条目,不创建新条目,等同于
  • 示例
    // 替换当前路由,禁止返回上一页this.$router.replace(\'/login\');
3. this.$router.go(n)
  • 作用:在历史记录中前进或后退,参数 n 为步数。
  • 示例
    this.$router.go(1); // 前进一页(等同于 history.forward())this.$router.go(-1); // 后退一页(等同于 history.back())this.$router.go(3); // 前进三页
二、与 的对比
方式 适用场景 特点 静态导航链接(如导航栏、菜单) 声明式,简单直观 编程式路由导航 动态逻辑跳转(如按钮点击、条件判断) 灵活,可结合业务逻辑,支持异步操作
三、典型场景
1. 按钮点击跳转
 export default { methods: { handleLogin() { // 登录逻辑... this.$router.push(\'/dashboard\'); } }}
2. 条件跳转
// 根据用户权限跳转if (this.isAdmin) { this.$router.push(\'/admin\');} else { this.$router.push(\'/user\');}
3. 异步操作后跳转
async fetchData() { await this.api.getUser(); this.$router.replace(\'/profile\'); // 替换路由,禁止返回}
4. 带参数跳转
// 传递 params 参数this.$router.push({ name: \'product\', params: { id: this.selectedId } });// 传递 query 参数this.$router.push({ path: \'/search\', query: { page: 2 } });
四、注意事项
  1. 路由钩子与导航守卫
    编程式导航同样会触发全局导航守卫(如 beforeEach)和路由独享守卫(如 beforeEnter),需注意逻辑顺序。

  2. 命名路由优先
    传递动态参数(如 params)时,建议使用命名路由,避免路径拼接错误。

  3. 错误处理
    导航失败(如路由不存在)会返回一个被拒绝的 Promise,可以通过 .catch 捕获错误:

    this.$router.push(\'/non-existent\').catch(err => { console.error(\'导航失败:\', err);});
五、总结

编程式路由导航是 Vue Router 提供的 JavaScript 方式控制路由跳转 的能力,通过 pushreplacego 等方法实现灵活的导航逻辑,适用于需要动态控制路由的场景。与 结合使用,能满足各种复杂的路由需求。

缓存路由组件

在 Vue Router 中,缓存路由组件 是提升单页应用性能和用户体验的重要手段,主要通过 组件实现。以下是核心机制与使用场景:

Vue2下

一、核心原理
  • 普通组件行为:组件在切换时会被销毁(beforeDestroy/destroyed),再次进入时重新创建(created/mounted)。
  • 缓存组件行为:使用 包裹的组件,在切换时不会被销毁,而是进入“缓存状态”(deactivated),再次进入时直接恢复(activated),避免重复渲染和数据请求。
二、基础用法(✔️)
1. 全局缓存所有路由组件
   
2. 缓存特定组件(推荐)

通过 include/exclude 指定缓存组件名称(组件的 name 选项):

//include:组件名  
3. 动态缓存(通过路由元信息)

在路由配置中添加 meta.keepAlive,动态控制是否缓存:

// router.jsconst routes = [ { path: \'/home\', component: Home, meta: { keepAlive: true } // 需要缓存 }, { path: \'/detail\', component: Detail, meta: { keepAlive: false } // 不需要缓存 }];
    
语法与作用说明

在 Vue 中, 组件的 include 属性用于指定需要缓存的组件名称,值可以是字符串、正则表达式,也可以是数组(数组里放组件名称字符串) 。你代码里的写法:

<keep-alive :include=\"[\'News\',\'Message\']\"> <router-view></router-view> </keep-alive>

表示:仅缓存名称为 NewsMessage 的组件,当这两个组件在
中切换时,会被缓存(组件实例不会销毁,再次进入时不会重新执行创建阶段的钩子,而是触发 activated 等缓存相关钩子 ),其他未匹配名称的组件则不会被缓存。

关键前提条件

  1. 组件需有 name 选项NewsMessage 组件必须在自身定义中显式声明 name,且名称要和 include 里的字符串严格一致,
    示例:
// News.vue export default{ name: \'News\', // 必须声明,且和 include 里的 \'News\' 一致 // ... }// Message.vue export default { name: \'Message\', // ... }

如果是单文件组件未手动写 name,Vue 会默认将文件名作为 name(比如 News.vue 会默认 name: \'News\' ),但为了清晰和避免意外,建议手动声明。

  1. 配合路由使用场景: 这种写法通常用于在路由切换时,缓存特定的页面级组件(即通过 router-view 渲染的组件 )。比如 NewsMessage 是两个路由组件,通过路由配置映射到不同路径,当在这两个路由间切换时,就能利用
    keep-alive 缓存它们的状态。

常见扩展用法对比

  • 字符串形式include=\"News\" ,只能缓存一个组件,适合单一目标场景。
  • 正则形式:include=\"/News|Message/\"(需结合 v-bind 绑定,因为是 JavaScript 表达式 ),用正则匹配组件名称,灵活但相对难维护。
  • 数组形式(你代码里的写法)::include=\"[\'News\',\'Message\']\" ,清晰列出要缓存的组件,适合明确知道缓存范围的场景,也是实际项目里常用的方式。

只要满足上述组件 name 匹配等条件,你的写法是合法且推荐的,能精准控制缓存范围,避免不必要的组件缓存,节省内存、提升性能。

核心区别:静态字符串 vs 动态绑定数组
写法 语法类型 解析方式 include=\"Home,User,Product\" 静态字符串 Vue 会直接将字符串按逗号分割为数组 [\'Home\', \'User\', \'Product\'] :include=\"[\'Home\',\'User\']\" 动态绑定 JavaScript 数组 通过 v-bind 绑定 JS 表达式,需在 Vue 实例中定义或直接写数组字面量
三、缓存组件的生命周期钩子
  • activated:组件被激活时触发(首次加载或从缓存中恢复)。
  • deactivated:组件被缓存时触发(离开但不销毁)。

典型应用:在 activated 中判断是否需要重新加载数据:

export default { data() { return { data: null, loaded: false }; }, activated() { if (!this.loaded) { this.fetchData(); // 只在首次加载或数据过期时请求 this.loaded = true; } }, methods: { fetchData() { // API 请求... } }};
四、适用场景
  1. 频繁切换的页面:如标签页(Tab),避免每次切换都重新渲染。
  2. 数据加载耗时的页面:如商品详情页,缓存后二次访问无需重新请求数据。
  3. 需要保存状态的表单:如多步骤表单,切换步骤时保留已填写内容。
五、注意事项
  1. 内存占用:过多缓存组件会增加内存开销,建议仅缓存关键页面。
  2. 数据更新:缓存组件不会触发 mounted,需在 activated 中处理数据更新。
  3. 组件复用问题:动态路由(如 /user/:id)切换不同参数时,组件会复用而不触发 activated,需通过 watch 监听 $route 变化:
    watch: { $route() { this.fetchData(); // 路由参数变化时重新加载 }}
六、高级用法
1. 结合 max 属性限制缓存数量
  
2. 动态控制缓存状态

通过修改路由元信息或组件 name,在运行时动态决定是否缓存:

// 导航守卫中动态设置router.beforeEach((to, from, next) => { if (to.name === \'Detail\' && from.name === \'List\') { to.meta.keepAlive = true; // 从列表页进入详情页时缓存 } next();});
七、总结

缓存路由组件是优化 SPA 性能的重要手段,通过 实现组件复用,避免重复渲染和数据请求。合理使用 include/exclude、路由元信息及生命周期钩子,能在提升体验的同时避免内存问题。

案例

以下是关于 Vue Router 核心特性的综合解析,通过 电商商品详情页 案例串联所有知识点:

案例场景

假设你正在开发一个电商网站,需要实现以下功能:

  • 从商品列表页点击商品,跳转到详情页(携带商品 ID)。
  • 详情页包含 基本信息用户评价相关推荐 三个子页面(嵌套路由)。
  • 评价页支持按时间/评分筛选(query 参数)。
  • 商品详情页需要缓存,避免重复加载数据。
1. 路由配置(router.js
const routes = [ // 商品列表页 { path: \'/products\', component: ProductsList }, // 商品详情页(动态路由 + 嵌套路由) { path: \'/product/:id\', // params 参数:商品 ID name: \'ProductDetail\', // 命名路由 component: ProductDetail, props: true, // 启用 props 接收 params children: [ { path: \'\', redirect: \'info\' }, // 默认子路由 { path: \'info\', component: ProductInfo }, { path: \'reviews\', component: ProductReviews }, { path: \'related\', component: RelatedProducts } ] }];
2. 路由传参与导航
(1)query 参数(筛选条件)
 按时间排序export default { computed: { sortType() { return this.$route.query.sort || \'default\'; } }}
(2)命名路由 + params 参数(商品 ID)
 {{ item.name }}methods: { goToDetail() { this.$router.push({ name: \'ProductDetail\', params: { id: this.selectedId } }); }}
(3)路由的 props 配置(简化参数接收)
// 路由配置{ path: \'/product/:id\', component: ProductDetail, props: true // 将 params 转为组件 props}// 在 ProductDetail 组件中直接接收export default { props: [\'id\'], mounted() { this.fetchProductData(this.id); }}
3. router-link 的 replace 属性
 立即购买
4. 缓存路由组件(keep-alive
   export default { activated() { // 组件被激活时触发(缓存后首次加载或重新显示) if (!this.$route.meta.loaded) { this.fetchData(); // 只在首次加载时请求数据 this.$route.meta.loaded = true; } }, deactivated() { // 组件被缓存时触发(隐藏但不销毁) }}
5. 完整流程图
商品列表页(/products) └── 点击商品(携带 id 参数) ↓商品详情页(/product/123) ├── 默认显示:基本信息(/product/123/info) ├── 切换到评价页(/product/123/reviews?sort=time) │ └── query 参数控制筛选逻辑 └── 切换到相关推荐(/product/123/related)[缓存机制]当从详情页跳转到其他页面时,详情页组件不会销毁,再次返回时直接显示缓存内容,无需重新加载数据。
核心知识点总结
特性 作用 示例 query 参数 用于传递可选参数(如筛选条件),显示在 URL 中(?sort=time)。 命名路由 为路由定义名称,避免硬编码路径,提高可维护性。 name: \'ProductDetail\' + this.$router.push({ name: \'...\' }) params 参数 用于传递必需参数(如 ID),通过动态路由(:id)接收。 path: \'/product/:id\' + this.$route.params.id props 配置 将 params 转为组件 props,解耦组件与路由。 props: true + export default { props: [\'id\'] } replace 属性 替换当前历史记录,禁止返回上一页。 缓存路由组件 使用 keep-alive 缓存组件状态,避免重复渲染。 + activated() 生命周期钩子
两个新的生命周期钩子
  1. ** 作用**:路由组件所独有的两个钩子,用于捕获路由组件的激活状态。
  2. 具体名字
    1. activated 路由组件被激活时触发。
    2. deactivated 路由组件失活时触发。Vue2下

Vue UI组件库

一、移动端组件库

库名 特点 技术栈 官网地址 适用场景 Vant 有赞出品,更新活跃,组件全 Vue 2/3 https://vant-contrib.gitee.io/vant/ 电商、表单、中大型项目 NutUI 京东出品,轻量高效 Vue 2/3 https://nutui.jd.com/ 快速迭代项目 Cube UI 滴滴开源,定制性强 Vue 2 https://didi.github.io/cube-ui/ 需深度定制的移动端项目 Mint UI 经典老库(维护停滞) Vue 2 https://github.com/ElemeFE/mint-ui 旧项目维护(慎用于新项目)

二、PC 端组件库

库名 特点 技术栈 官网地址 适用场景 Element UI 元老级,文档完善 Vue 2 https://element.eleme.cn/ 企业后台、管理系统 Element Plus Element 官方 Vue 3 版本 Vue 3 https://element-plus.org/ 新项目(Vue 3 技术栈) View UI 原 iView,设计现代 Vue 2/3 https://www.iviewui.com/ 中后台系统、数据可视化 Ant Design Vue 阿里系,组件丰富 Vue 2/3 https://www.antdv.com/ 复杂业务系统、中台产品

三、跨端/全场景组件库

库名 特点 技术栈 官网地址 适用场景 Naive UI 全场景,性能优异 Vue 3 https://www.naiveui.com/ 中大型 Web 应用(Vue 3) Arco Design 字节跳动出品,设计统一 Vue 2/3 https://arco.design/vue 企业级产品、多端一致性需求

Vue2下

四、使用建议

  1. 技术栈匹配

    • Vue 2:选 Element UI、Vant、View UI
    • Vue 3:选 Element Plus、Naive UI、Ant Design Vue
  2. 场景选择

    • 电商/移动端:Vant(功能最全)
    • 企业后台:Element UI/Plus(稳定)或 Ant Design Vue(组件丰富)
    • 快速开发:NutUI(体积小)或 View UI(设计现代)
  3. 避坑指南

    • 避免在新项目中使用 Mint UI(已停止维护)
    • 注意组件库与 Vue 版本的兼容性
    • 按需引入组件以减小打包体积(参考各库文档)

五、快速上手示例(Vant)

# 安装npm i vant@next -S # Vue 3 项目npm i vant -S # Vue 2 项目# 按需引入(推荐)npm i unplugin-vue-components unplugin-auto-import -D
// vite.config.jsimport { defineConfig } from \'vite\'import AutoImport from \'unplugin-auto-import/vite\'import Components from \'unplugin-vue-components/vite\'import { VantResolver } from \'unplugin-vue-components/resolvers\'export default defineConfig({ plugins: [ AutoImport({ resolvers: [VantResolver()], }), Components({ resolvers: [VantResolver()], }), ],})