前言
vue-router是vue的一个重难点,要想一次就学废还是有点难度的,我花了一天多的时间整理,还算是比较全面的,相关的钩子之前写过了,这里就不在赘述了
什么是前端路由
通俗易懂的概念:Hash地址与组件之间的对应关系
前端路由的工作方式
- 用户点击了页面上的路由链接
- 导致了URL地址栏中的Hash值发生了变化
- 前端路由监听到了Hash地址的变化
- 把当前Hash地址对应的组件渲染到浏览器中
vue-router使用步骤
- 安装
npm i vue-router
2.导入路由
import Vue from 'vue'
import VueRouter from 'vue-router'
3.注册 vue-router
// 在vue中,使用使用vue的插件,都需要调用Vue.use()
Vue.use(VueRouter)
4.设置匹配规则
const routes = [
{
path: '/', //默认hash值路径
redirect:'/find' // 重定向到find
}
,
{
path: '/find',
component: Find
},
{
// 动态传参方式1: :表示动态站位 id自定义
path: '/My/:id',
component: My,
//动态传参方式2:开启 props 属性 传参
props:true
},
{
path: '/part',
component: Part,
redirect:'/part/tab1',
// 通过 children 属性,声明嵌套子路由规则
children: [
{
// 默认子路由: 如果children 数组中,某个路由规则的path值为空字符串,则默认展示该子路由
// 子路由 path 后面不要加 /
path: 'tab1',
component:Tab1
},
{
path: 'tab2',
component:Tab2
}
]
},
{
path: '/part/:name',
component: Part,
props: true
},
{ // 路由404 设置
path: '*',
component:NotFound
}
]
5.实例化 router
const router = new VueRouter({
routes,
mode:"history",// 历史记录模式
})
6.导出 router
export default router
7.导入路由并挂载
在main点js中
// 全局导入路由
import router from './router'
new Vue({
router,// 挂载路由
render: h => h(App),
}).$mount('#app')
路由配置项
路由常用的配置项总共有如下几个:
-
path:要请求的hash地址
-
component:要展示的组件
-
redirect:重定向,指定一个新的路由地址
-
children:通过 children 属性,声明嵌套子路由规则
-
name:配置中给某个路由设置名称
-
props:路由解耦,路由传参的一种方式,针对动态路由
-
meta:路由元信息,当前路由所携带的一些信息
vue路由 - 声明式导航
- vue-router提供了一个全局组件 router-link
- router-link实质上最终会渲染成a链接 to属性等价于提供 href属性(to无需#)
- router-link提供了声明式导航高亮的功能(自带类名)
声明式导航是写在template标签里,通过标签来触发
<template>
<div>
<div class="footer_wrap">
//声明式导航会渲染成a链接
<router-link to="/find">发现音乐</router-link>
<router-link to="/my">我的音乐</router-link>
<router-link to="/Part">朋友</router-link>
</div>
<div class="top">
//要展示组件的占位符
<router-view></router-view>
</div>
</div>
</template>
声明导航 - 类名区别
观察路由嵌套导航的样式
- router-link-exact-active (精确匹配) url中hash值路径, 与href属性值完全相同, 设置此类名
- router-link-active (模糊匹配) url中hash值, 包含href属性值这个路径
vue路由 - 编程式导航
编程式导航:通过调用JavaScript形式的API实现导航的方式,叫做编程式导航
除了使用 <router-link> 创建 a 标签来定义导航链接,我们还可以借助 router 的实例方法,通过编写代码来实现。
router.push(location, onComplete?, onAbort?)
注意:在 Vue 实例内部,你可以通过 $router 访问路由实例。因此你可以调用 this.$router.push。
想要导航到不同的 URL,则使用 router.push 方法。这个方法会向 history 栈添加一个新的记录,所以,当用户点击浏览器后退按钮时,则回到之前的 URL。
当你点击 <router-link> 时,这个方法会在内部调用,所以说,点击 <router-link :to="..."> 等同于调用 router.push(...)。
| 声明式 | 编程式 |
|---|---|
<router-link :to="..."> | router.push(...) |
// 字符串
router.push('home')
// 对象
router.push({ path: 'home' })
// 命名的路由
router.push({ name: 'user', params: { userId: '123' }})
// 带查询参数,变成 /register?plan=private
router.push({ path: 'register', query: { plan: 'private' }})
注意:如果提供了 path,params 会被忽略,上述例子中的 query 并不属于这种情况。取而代之的是下面例子的做法,你需要提供路由的 name 或手写完整的带有参数的 path:
const userId = '123'
router.push({ name: 'user', params: { userId }}) // -> /user/123
router.push({ path: `/user/${userId}` }) // -> /user/123
// 这里的 params 不生效
router.push({ path: '/user', params: { userId }}) // -> /user
同样的规则也适用于 router-link 组件的 to 属性。
router.replace(location, onComplete?, onAbort?)
跟 router.push 很像,唯一的不同就是,它不会向 history 添加新记录,而是跟它的方法名一样 —— 替换掉当前的 history 记录。
| 声明式 | 编程式 |
|---|---|
<router-link :to="..." replace> | router.replace(...) |
router.go(n)
这个方法的参数是一个整数,意思是在 history 记录中向前或者后退多少步,类似 window.history.go(n)。
示例
// 在浏览器记录中前进一步,等同于 history.forward()
router.go(1)
// 后退一步记录,等同于 history.back()
router.go(-1)
// 前进 3 步记录
router.go(3)
// 如果 history 记录不够用,那就默默地失败呗
router.go(-100)
router.go(100)
路由嵌套
通过路由实现组件的嵌套展示,在现有的一级路由下, 再嵌套二级路由,叫做路由嵌套
const router = new VueRouter({
routes: [
{
path: '/user/:id',
component: User,
children: [
{
// 当 /user/:id/profile 匹配成功,
// UserProfile 会被渲染在 User 的 <router-view> 中
path: 'profile',
component: UserProfile
},
{
// 当 /user/:id/posts 匹配成功
// UserPosts 会被渲染在 User 的 <router-view> 中
path: 'posts',
component: UserPosts
}
]
}
]
})
路由传参
格式
this.$router.push({
path: "路由路径"
name: "路由名",
query: {
"参数名": 值
}
params: {
"参数名": 值
}
})
// 对应路由接收 $route.params.参数名 取值
// 对应路由接收 $route.query.参数名 取值
格外注意: 使用path会自动忽略params
query参数
传参方式一
// <!-- 跳转路由并携带query参数,to的字符串写法 -->
<router-link :to="`/home/message/detail?id=${m.id}&title=${m.title}`">{{m.title}}</router-link>
方式二
<!-- 跳转路由并携带query参数,to的对象写法 -->
<router-link :to="{
path:'/home/message/detail',
query:{
id:m.id,
title:m.title
}
}">
{{m.title}}
</router-link>
接收参数
// 对应路由接收 $route.query.参数名
<li>消息编号:{{$route.query.id}}</li>
<li>消息标题:{{$route.query.title}}</li>
params参数
方式一
<!-- 跳转路由并携带params参数,to的字符串写法 -->
<router-link :to="`/home/message/detail/${m.id}/${m.title}`">{{m.title}}</router-link>
方式二
<!-- 跳转路由并携带params参数,to的对象写法 -->
<router-link :to="{
name:'xiangqing',
params:{
id:m.id,
title:m.title
}
}">
{{m.title}}
</router-link>
接收参数
// 对应路由接收 $route.params.参数名
<li>消息编号:{{$route.params.id}}</li>
<li>消息标题:{{$route.params.title}}</li>
route 与 router区别
$route是路由的参数对象,包括 path,params,hash,query,fullPath,matched,name 等路由信息参数。
$router是VueRouter的一个对象,通过Vue.use(VueRouter)和Vue构造函数得到一个router的实例对象,这个对象中是一个全局的对象,他包含了所有的路由,包含了许多关键的对象和属性
路由的props配置
props为对象模式
值为对象,该对象中的所有key-value都会以props的形式传给组件,配置在哪个路由规则内就传给谁
const router = new VueRouter({
routes: [
{
path: '/promotion/from-newsletter',
component: Promotion,
props: { newsletterPopup: false }
}
]
})
props为布尔模式
值为布尔值,若布尔值为真,就会把该路由组件收到的所有params参数,以props的形式传给Detail组件
const router = new VueRouter({
routes: [
{
path: '/promotion/from-newsletter',
component: Promotion,
props:true
}
]
})
props为函数模式
const router = new VueRouter({
routes: [
{
path: '/search',
component: SearchUser,
props: route => ({ query: route.query.q })
}
]
})
vue-router的两种模式hash 模式和 history 模式
hash模式与history模式是两种单页应用的路由模式:
hash模式 :
底层原理是通过hashChange 实现,使用 URL 的 hash 来模拟一个完整的 URL, 其显示的网络路径中会有 “#” 号,hash 虽然出现URL中,但不会被包含在HTTP请求中,对后端完全没有影响,因此改变hash后刷新, 也不会有问题
history模式:
底层原理是通过replaceState(), pushState()实现,history模式就是美化后的hash模式,路径中不包含“#”。依赖于Html5 的 history api 项目打包上线由于改变了地址, 刷新时会按照修改后的地址请求后端, 需要后端配置处理, 将地址访问做映射, 否则会404
解决方案:
为什么哈希模式打包不会出现问题?是因为哈希模式会默认去index页面,而history运行代码发现没有token会去login页面,但打包上线只有一个index页面,这就需要后端的配合,看后端是什么应用,但是原理都是一样的,需要后端把请求都转到index页面
宝,你都看到这了不给我一个star嘛?
PS: 如果内容有错误的地方欢迎指出(觉得看着不理解不舒服想吐槽也完全没问题);如果有帮助,欢迎点赞和收藏,转载请著明出处,如果有问题也欢迎私信交流