Vue2篇——第六章 Vue 路由(VueRouter)全解析

发布于:2025-08-19 ⋅ 阅读:(17) ⋅ 点赞:(0)

目录

一、单页应用程序介绍

二、路由介绍

三、路由的基本使用

四、组件的存放目录问题

五、路由的封装抽离

六、声明式导航-导航链接

七、声明式导航-两个类名

八、声明式导航-自定义类名(了解)

九、声明式导航-查询参数传参

十、声明式导航-动态路由传参

十一、动态路由参数的可选符(了解)

十二、Vue路由-重定向

十三、Vue路由-404

十四、Vue路由-模式设置

十五、编程式导航-两种路由跳转方式

十六、编程式导航-path路径跳转传参

十七、编程式导航-name命名路由传参

        十八. 路由配置技巧

        十九. 导航优化技术

        二十. 数据请求与渲染模式

        二十一. 路由传参技术

        二十二. 组件缓存优化

        二十三. 导航控制


本文全面介绍了Vue路由(VueRouter)的核心概念与实践技巧。主要内容包括:1. 路由基础:单页应用与路由概念、基本使用步骤(5+2)、组件目录规范;2. 导航方式:声明式导航(router-link)与编程式导航(push/replace/go)的用法与区别;3. 传参技术:查询参数(query)和动态路由(params)两种传参方式;4. 高级配置:重定向、404页面、路由模式(hash/history)设置;5. 优化技巧:路由封装抽离、组件缓存(keep-alive)、导航控制等。文章通过网易云音乐等实例,详细演示了路由在实际项目中的应用场景和最佳实践,帮助开发者掌握Vue路由的完整知识体系。

一、单页应用程序介绍

1.概念

单页应用程序:SPA【Single Page Application】是指所有的功能都在一个html页面上实现

2.具体示例

单页应用网站: 网易云音乐 网易云音乐

多页应用网站:京东 京东(JD.COM)-正品低价、品质保障、配送及时、轻松购物!

3.单页应用 VS 多页面应用

单页应用类网站:系统类网站 / 内部网站 / 文档类网站 / 移动端站点

多页应用类网站:公司官网 / 电商类网站

4.总结

1.什么是单页面应用程序?

​ 所有功能在一个html页面上实现

2.单页面应用优缺点?

​ 优点:按需更新性能高,开发效率高,用户体验好

​ 缺点:学习成本,首屏加载慢, 不利于SEO

3.单页应用场景?

​ 系统类网站 / 内部网站 / 文档类网站 / 移动端站点

二、路由介绍

1.思考

单页面应用程序,之所以开发效率高,性能好,用户体验好

最大的原因就是:页面按需更新

比如当点击【发现音乐】和【关注】时,只是更新下面部分内容,对于头部是不更新的

要按需更新,首先就需要明确:访问路径组件的对应关系!

访问路径 和 组件的对应关系如何确定呢? 路由

2.路由的介绍

生活中的路由:设备和ip的映射关系

Vue中的路由:路径和组件映射关系

3.总结

  • 什么是路由?

    路由是一种映射关系

  • Vue中的路由是什么?

    路径和组件的映射关系

    根据路由就能知道不同路径的,应该匹配渲染哪个组件

三、路由的基本使用

1.目标

认识插件 VueRouter,掌握 VueRouter 的基本使用步骤

2.作用

修改地址栏路径时,切换显示匹配的组件

3.说明

Vue 官方的一个路由插件,是一个第三方包

4.官网

Vue Router

5.VueRouter的使用(5+2)

固定5个固定的步骤(不用死背,熟能生巧)

  1. 下载 VueRouter 模块到当前工程,版本3.6.5

    yarn add vue-router@3.6.5 或 npm install vue-router@3.6.5

  2. main.js中引入VueRouter

    import VueRouter from 'vue-router'

  3. 安装注册

    Vue.use(VueRouter)

  4. 创建路由对象

    const router = new VueRouter()

  5. 注入,将路由对象注入到new Vue实例中,建立关联

    new Vue({
      render: h => h(App),
      router:router
    }).$mount('#app')
    ​

当我们配置完以上5步之后 就可以看到浏览器地址栏中的路由 变成了 /#/的形式。表示项目的路由已经被Vue-Router管理了

6.代码示例

main.js

// 路由的使用步骤 5 + 2
// 5个基础步骤
// 1. 下载 v3.6.5
// yarn add vue-router@3.6.5
// 2. 引入
// 3. 安装注册 Vue.use(Vue插件)
// 4. 创建路由对象
// 5. 注入到new Vue中,建立关联
​
​
import VueRouter from 'vue-router'
Vue.use(VueRouter) // VueRouter插件初始化
​
const router = new VueRouter()
​
new Vue({
  render: h => h(App),
  router
}).$mount('#app')

7.两个核心步骤

  1. 创建需要的组件 (views目录),配置路由规则

  1. 配置导航,配置路由出口(路径匹配的组件显示的位置)

    App.vue
    
    <div class="footer_wrap">
      <a href="#/find">发现音乐</a>
      <a href="#/my">我的音乐</a>
      <a href="#/friend">朋友</a>
    </div>
    <div class="top">
      <router-view></router-view>
    </div>

8.总结

  1. 如何实现 路径改变,对应组件 切换,应该使用哪个插件?

    ​ Vue官方插件VueRouter

  2. Vue-Router的使用步骤是什么(5+2)?

5个基础步骤:

​ (1)下包

​ (2)引入

​ (3)Vue.use安装注册

​ (4)创建路由对象

​ (5)注入Vue实例

2个核心步骤:

​ (1)创建组件,配置规则(路径组件的匹配关系)

​ (2)配置导航,配置路由出口 利用内置的 router-view(组件展示的位置

四、组件的存放目录问题

注意: .vue文件 本质无区别

1.组件分类

.vue文件分为2类,都是 .vue文件(本质无区别)

  • 页面组件 (配置路由规则时使用的组件)

  • 复用组件(多个组件中都使用到的组件)

2.存放目录

分类开来的目的就是为了 更易维护

  1. src/views文件夹

    页面组件 - 页面展示 - 配合路由用

  2. src/components文件夹

    复用组件 - 展示数据 - 常用于复用

3.总结

  • 组件分类有哪两类?分类的目的?

​ 页面组件和复用组件,目的是便于维护

  • 不同分类的组件应该放在什么文件夹?作用分别是什么?

    页面组件——views文件夹 => 配合路由,页面展示

    复用组件——components文件夹 => 封装复用

五、路由的封装抽离

问题:所有的路由配置都在main.js中合适吗?

目标:将路由模块抽离出来。 好处:拆分模块,利于维护

路径简写:

脚手架环境下 @指代src目录,可以用于快速引入组件

总结:

  • 路由模块的封装抽离的好处是什么?

    拆分模块,利于维护

  • 以后如何快速引入组件?

    ​ 基于@指代src目录,从src目录出发找组件

六、声明式导航-导航链接

1.需求

实现导航高亮效果

如果使用a标签进行跳转的话,需要给当前跳转的导航加样式,同时要移除上一个a标签的样式,太麻烦!!!

2.解决方案

vue-router 提供了一个全局组件 router-link (取代 a 标签)

  • 能跳转,配置 to 属性指定路径(必须) 。本质还是 a 标签 ,to 无需 #

  • 能高亮,默认就会提供高亮类名,可以直接设置高亮样式

语法: <router-link to="path的值">发现音乐</router-link>

  <div>
    <div class="footer_wrap">
      <router-link to="/find">发现音乐</router-link>
      <router-link to="/my">我的音乐</router-link>
      <router-link to="/friend">朋友</router-link>
    </div>
    <div class="top">
      <!-- 路由出口 → 匹配的组件所展示的位置 -->
      <router-view></router-view>
    </div>
  </div>

3.通过router-link自带的两个样式进行高亮

使用router-link跳转后,我们发现。当前点击的链接默认加了两个class的值 router-link-exact-activerouter-link-active

我们可以给任意一个class属性添加高亮样式即可实现功能

4.总结

  • router-link是什么?

​ vue-router提供的全局组件,用于替换a标签

  • router-link怎么用?

    <router-link to="/路径值"></router-link>

    ​ 必须传入to属性,指定路由路径值

  • router-link的好处是什么?

    ​ 能跳转 能高亮(自带激活时的类名

七、声明式导航-两个类名

当我们使用<router-link></router-link>跳转时,自动给当前导航加了两个类名

模糊匹配(用的多)

to="/my" 可以匹配 /my /my/a /my/b ....

只要是以/my开头的路径 都可以和 to="/my"匹配到

精确匹配

to="/my" 仅可以匹配 /my

3.在地址栏中输入二级路由查看类名的添加

4.总结

  • router-link 会自动给当前导航添加两个类名,有什么区别呢?

​ router-link-active 模糊匹配(用的多)

​ router-link-exact-active 精确匹配

八、声明式导航-自定义类名(了解)

1.问题

router-link的两个高亮类名 太长了,我们希望能定制怎么办

2.解决方案

我们可以在创建路由对象时,额外配置两个配置项即可。 linkActiveClasslinkExactActiveClass

const router = new VueRouter({
  routes: [...],
  linkActiveClass: "类名1",
  linkExactActiveClass: "类名2"
})

3.代码演示

// 创建了一个路由对象
const router = new VueRouter({
  routes: [
    ...
  ], 
  linkActiveClass: 'active', // 配置模糊匹配的类名
  linkExactActiveClass: 'exact-active' // 配置精确匹配的类名
})

4.总结

如何自定义router-link的两个高亮类名?

只需在new VueRouter里面配置linkActiveClass 模糊匹配 类名自定义和linkExactActiveClass精确匹配 类名自定义

九、声明式导航-查询参数传参

1.目标

在跳转路由时,进行传参

比如:现在我们在搜索页点击了热门搜索链接,跳转到详情页,需要把点击的内容带到详情页,改怎么办呢?

2.跳转传参

我们可以通过两种方式,在跳转的时候把所需要的参数传到其他页面中

  • 查询参数传参

  • 动态路由传参

3.查询参数传参

  • 如何传参?

    <router-link to="/path?参数名=值"></router-link>

  • 如何接受参数

    固定用法:$router.query.参数名

4.代码演示

App.vue

<template>
  <div id="app">
    <div class="link">
      <router-link to="/home">首页</router-link>
      <router-link to="/search">搜索页</router-link>
    </div>
​
    <router-view></router-view>
  </div>
</template>
​
<script>
export default {};
</script>
​
<style scoped>
.link {
  height: 50px;
  line-height: 50px;
  background-color: #495150;
  display: flex;
  margin: -8px -8px 0 -8px;
  margin-bottom: 50px;
}
.link a {
  display: block;
  text-decoration: none;
  background-color: #ad2a26;
  width: 100px;
  text-align: center;
  margin-right: 5px;
  color: #fff;
  border-radius: 5px;
}
</style>
Home.vue

<template>
  <div class="home">
    <div class="logo-box"></div>
    <div class="search-box">
      <input type="text">
      <button>搜索一下</button>
    </div>
    <div class="hot-link">
      热门搜索:
      <router-link to="">黑马程序员</router-link>
      <router-link to="">前端培训</router-link>
      <router-link to="">如何成为前端大牛</router-link>
    </div>
  </div>
</template>
​
<script>
export default {
  name: 'FindMusic'
}
</script>
​
<style>
.logo-box {
  height: 150px;
  background: url('@/assets/logo.jpeg') no-repeat center;
}
.search-box {
  display: flex;
  justify-content: center;
}
.search-box input {
  width: 400px;
  height: 30px;
  line-height: 30px;
  border: 2px solid #c4c7ce;
  border-radius: 4px 0 0 4px;
  outline: none;
}
.search-box input:focus {
  border: 2px solid #ad2a26;
}
.search-box button {
  width: 100px;
  height: 36px;
  border: none;
  background-color: #ad2a26;
  color: #fff;
  position: relative;
  left: -2px;
  border-radius: 0 4px 4px 0;
}
.hot-link {
  width: 508px;
  height: 60px;
  line-height: 60px;
  margin: 0 auto;
}
.hot-link a {
  margin: 0 5px;
}
</style>
Search.vue

<template>
  <div class="search">
    <p>搜索关键字: 黑马程序员</p>
    <p>搜索结果: </p>
    <ul>
      <li>.............</li>
      <li>.............</li>
      <li>.............</li>
      <li>.............</li>
    </ul>
  </div>
</template>
​
<script>
export default {
  name: 'MyFriend',
  created () {
    // 在created中,获取路由参数
  }
}
</script>
​
<style>
.search {
  width: 400px;
  height: 240px;
  padding: 0 20px;
  margin: 0 auto;
  border: 2px solid #c4c7ce;
  border-radius: 5px;
}
</style>
router/index.js

import Home from '@/views/Home'
import Search from '@/views/Search'
import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter) // VueRouter插件初始化
​
// 创建了一个路由对象
const router = new VueRouter({
  routes: [
    { path: '/home', component: Home },
    { path: '/search', component: Search }
  ]
})
​
export default router
main.js

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

十、声明式导航-动态路由传参

1.动态路由传参方式

  • 配置动态路由

    动态路由后面的参数可以随便起名,但要有语义

    const router = new VueRouter({
      routes: [
        ...,
        { 
          path: '/search/:words', 
          component: Search 
        }
      ]
    })

  • 配置导航链接

    to="/path/参数值"

  • 对应页面组件接受参数

    $route.params.参数名

    params后面的参数名要和动态路由配置的参数保持一致

2.查询参数传参 VS 动态路由传参

  1. 查询参数传参 (比较适合传多个参数)

    1. 跳转:to="/path?参数名=值&参数名2=值"

    2. 获取:$route.query.参数名

  2. 动态路由传参 (优雅简洁,传单个参数比较方便)

    1. 配置动态路由:path: "/path/:参数名"

    2. 跳转:to="/path/参数值"

    3. 获取:$route.params.参数名

    注意:动态路由也可以传多个参数,但一般只传一个

3.总结

声明式导航跳转时, 有几种方式传值给路由页面?

  • 查询参数传参(多个参数)

  • 动态路由传参(一个参数,优雅简洁)

十一、动态路由参数的可选符(了解)

1.问题

配了路由 path:"/search/:words" 为什么按下面步骤操作,会未匹配到组件,显示空白?

2.原因

/search/:words 表示,必须要传参数。如果不传参数,也希望匹配,可以加个可选符"?"

const router = new VueRouter({
  routes: [
    ...
    { path: '/search/:words?', component: Search }
  ]
})

十二、Vue路由-重定向

1.问题

网页打开时, url 默认是 / 路径,未匹配到组件时,会出现空白

2.解决方案

重定向 → 匹配 / 后, 强制跳转 /home 路径

3.语法

{ path: 匹配路径, redirect: 重定向到的路径 },
比如:
{ path:'/' ,redirect:'/home' }

4.代码演示

const router = new VueRouter({
  routes: [
    { path: '/', redirect: '/home'},
     ...
  ]
})

十三、Vue路由-404

1.作用

当路径找不到匹配时,给个提示页面

2.位置

404的路由,虽然配置在任何一个位置都可以,但一般都配置在其他路由规则的最后面

3.语法

path: "*" (任意路径) – 前面不匹配就命中最后这个

import NotFind from '@/views/NotFind'
​
const router = new VueRouter({
  routes: [
    ...
    { path: '*', component: NotFind } //最后一个
  ]
})

4.代码示例

NotFound.vue

<template>
  <div>
    <h1>404 Not Found</h1>
  </div>
</template>
​
<script>
export default {
​
}
</script>
​
<style>
​
</style>
router/index.js

...
import NotFound from '@/views/NotFound'
...
​
// 创建了一个路由对象
const router = new VueRouter({
  routes: [
     ...
    { path: '*', component: NotFound }
  ]
})
​
export default router

十四、Vue路由-模式设置

1.问题

路由的路径看起来不自然, 有#,能否切成真正路径形式?

2.语法

const router = new VueRouter({
    mode:'histroy', //默认是hash
    routes:[]
})

十五、编程式导航-两种路由跳转方式

1.问题

点击按钮跳转如何实现?

2.方案

编程式导航:用JS代码来进行跳转

3.语法

两种语法:

  • path 路径跳转 (简易方便)

  • name 命名路由跳转 (适合 path 路径长的场景)

4.path路径跳转语法

特点:简易方便

//简单写法
this.$router.push('路由路径')
​
//完整写法
this.$router.push({
  path: '路由路径'
})

5.name命名路由跳转

特点:适合 path 路径长的场景

语法:

  • 路由规则,必须配置name配置项

    { name: '路由名', path: '/path/xxx', component: XXX },

  • 通过name来进行跳转

    this.$router.push({
      name: '路由名'
    })

9.总结

编程式导航有几种跳转方式?

1. $router.push() (最常用)

  • 作用:导航到新页面,添加历史记录

  • 使用场景:普通页面跳转(可后退)

  • 示例

// 路径跳转
this.$router.push('/home')

// 对象形式(带参数)
this.$router.push({
  path: '/user',
  query: { id: 123 } // URL参数:/user?id=123
})

// 命名路由
this.$router.push({
  name: 'profile',
  params: { userId: 'abc' } // 路由参数:/profile/abc
})

2. $router.replace()

  • 作用:替换当前页面,不添加历史记录

  • 使用场景:登录页跳转首页(不可后退)

  • 示例

// 替换当前路由
this.$router.replace('/dashboard')

// 带参数替换
this.$router.replace({
  path: '/login',
  query: { redirect: '/admin' }
})

3. $router.go()

  • 作用:在历史记录中前进/后退

  • 使用场景:模拟浏览器前进后退按钮

  • 示例

// 后退1页(等同于浏览器后退按钮)
this.$router.go(-1)

// 前进2页
this.$router.go(2)

// 刷新当前页(实际效果是前进0页)
this.$router.go(0)

4. $router.back()

  • 作用等同于 go(-1),后退一页

  • 使用场景:返回上一页

  • 示例

// 返回上一页
this.$router.back()

5. $router.forward()

  • 作用等同于 go(1),前进一页

  • 使用场景:返回下一页(较少使用)

  • 示例

// 前进一页(如果存在)
this.$router.forward()


关键区别总结

方法 历史记录 使用频率 典型场景
push() 添加 ⭐⭐⭐⭐⭐ 常规导航(可回退)
replace() 替换 ⭐⭐⭐⭐ 登录跳转(不可回退)
go(n) 跳转 ⭐⭐ 前进/后退N步
back() 后退 ⭐⭐⭐ 返回上一页
forward() 前进 前进下一页

参数传递方式对比

1. 路径参数(params
// 发送方
this.$router.push({
  name: 'user', // 必须用命名路由
  params: { id: 1001 }
})

// 接收方(在目标组件)
this.$route.params.id // => 1001
2. 查询参数(query
// 发送方
this.$router.push({
  path: '/search',
  query: { keyword: 'vue' } // URL显示:/search?keyword=vue
})

// 接收方
this.$route.query.keyword // => "vue"
3. Hash 定位
// 跳转到指定锚点
this.$router.push('/about#contact')

// 获取hash
this.$route.hash // => "#contact"

最佳实践

  1. 优先使用命名路由

    // ✅ 推荐(更健壮)
    this.$router.push({ name: 'product', params: { id: 99 } })
    
    // ❌ 避免(路径改变需同步修改)
    this.$router.push('/product/99')

  2. 参数类型注意

    // 传递数字(params会自动转字符串)
    this.$router.push({ name: 'item', params: { id: 123 } })
    
    // 接收时转换类型
    const id = Number(this.$route.params.id)

  3. 路由守卫组合

    // 在导航前处理逻辑
    this.$router.push({
      path: '/checkout',
      query: { step: 2 }
    }).catch(err => {
      // 处理导航中断
      if (err.name !== 'NavigationDuplicated') {
        console.error('导航失败', err)
      }

十六、编程式导航-path路径跳转传参

1.问题

点击搜索按钮,跳转需要把文本框中输入的内容传到下一个页面如何实现?

2.两种传参方式

1.查询参数

2.动态路由传参

3.传参

两种跳转方式,对于两种传参方式都支持:

① path 路径跳转传参

② name 命名路由跳转传参

4.path路径跳转传参(query传参)

//简单写法
this.$router.push('/路径?参数名1=参数值1&参数2=参数值2')
//完整写法
this.$router.push({
  path: '/路径',
  query: {
    参数名1: '参数值1',
    参数名2: '参数值2'
  }
})

接受参数的方式依然是:$route.query.参数名

5.path路径跳转传参(动态路由传参)

//简单写法
this.$router.push('/路径/参数值')
//完整写法
this.$router.push({
  path: '/路径/参数值'
})

接受参数的方式依然是:$route.params.参数值

注意:path不能配合params使用

十七、编程式导航-name命名路由传参

1.name 命名路由跳转传参 (query传参)

this.$router.push({
  name: '路由名字',
  query: {
    参数名1: '参数值1',
    参数名2: '参数值2'
  }
})

2.name 命名路由跳转传参 (动态路由传参)

this.$router.push({
  name: '路由名字',
  params: {
    参数名: '参数值',
  }
})

3.总结

编程式导航,如何跳转传参?

1.path路径跳转

  • query传参

    this.$router.push('/路径?参数名1=参数值1&参数2=参数值2')
    this.$router.push({
      path: '/路径',
      query: {
        参数名1: '参数值1',
        参数名2: '参数值2'
      }
    })

  • 动态路由传参

    this.$router.push('/路径/参数值')
    this.$router.push({
      path: '/路径/参数值'
    })

2.name命名路由跳转

  • query传参

    this.$router.push({
      name: '路由名字',
      query: {
        参数名1: '参数值1',
        参数名2: '参数值2'
      }
    })

十八. 路由配置技巧

  • 一级路由配置:基础页面布局

routes: [
  { path: '/', component: Layout },
  { path: '/detail', component: ArticleDetail }
]
  • 嵌套路由(二级路由):实现局部内容切换

{
  path: '/',
  component: Layout,
  children: [
    { path: '/article', component: Article },
    { path: '/collect', component: Collect },
    { path: '/like', component: Like },
    { path: '/user', component: User }
  ]
}

十九. 导航优化技术

  • 路由链接高亮:使用router-link.router-link-active

<router-link to="/article">面经</router-link>

<style>
a.router-link-active {
  color: orange;
}
</style>

二十. 数据请求与渲染模式

  • axios集成:统一请求处理

async created() {
  const { data } = await axios.get('https://mock.boxuegu.com/mock/3083/articles')
  this.articleList = data.result.rows
}
  • 动态渲染:列表页和详情页数据绑定

<!-- 列表项 -->
<div v-for="item in articleList" :key="item.id">
  <p class="title">{{ item.stem }}</p>
</div>

<!-- 详情页 -->
<header class="header">
  <h1>{{ articleDetail.stem }}</h1>
</header>

二十一. 路由传参技术

  • 查询参数传参

// 发送
this.$router.push(`/detail?id=${item.id}`)

// 接收
this.$route.query.id
  • 动态路由传参(推荐):

// 路由配置
{ path: '/detail/:id', component: ArticleDetail }

// 发送
this.$router.push(`/detail/${item.id}`)

// 接收
this.$route.params.id

二十二. 组件缓存优化

  • keep-alive应用:提升用户体验

<keep-alive :include="['Layout']">
  <router-view></router-view>
</keep-alive>
  • 生命周期钩子:配合缓存使用

activated() {
  // 组件激活时触发(进入页面)
},
deactivated() {
  // 组件失活时触发(离开页面)
}

二十三. 导航控制

  • 编程式导航:灵活控制路由跳转

// 返回上一页
this.$router.back()

// 跳转详情页
this.$router.push(`/detail/${id}`)


网站公告

今日签到

点亮在社区的每一天
去签到