5、Vue 路由
Vue 中的路由允许不同的 URL 来访问不同的内容。
5.1、初识路由
程序开发中的路由分为后端路由和前端路由
5.1.1、后端路由
后端路由通过用户请求的 URL 分发到具体的处理程序,浏览器每次跳转到不同的 URL,都会重新访问服务器。
注意,浏览器每访问一次新页面的时候,都要向服务器发送请求,然后服务器会响应请求,返回新页面给浏览器,在这个过程中会有一定的网络延迟。
5.1.2、前端路由
把不同路由对应不同的内容或页面的任务交给前端来做。前端路由和后端路由的原理是类似的,但是实现的方式不一样。
前端路由在访问一个新页面的时候仅仅是变换了一下 hash 值而且,没有和服务端交互,所以不存在网络延迟,提升了用户体验。
5.2、vue-router
vue-router 是 Vue 官方推出的路由管理器,主要用于管理 URL,实现 URL 和组件的对应,以及通过 URL 进行组件之间的切换,从而使构建单页面应用变得更加简单。
5.2.1、vue-router 的工作原理
单页面应用的核心思想之一,就是更新视图而不重新请求页面。
在实现单页面前端路由时,提供了两种方式,分别是 hash 模式和 history 模式,根据 mode 参数来决定采用哪一种方式。
5.2.1.1、hash 模式
vue-router 默认为 hash 模式,使用 URL 的 hash 来模拟一个完整的 URL,当 URL 改变时,页面不会重新加载。
·# 就是 hash 符号,中文名为哈希符或者锚点,在 hash 符号后的值称为 hash 值。
5.2.1.2、history 模式
hash 模式的 URL 中会自带 # 号,影响 URL 的美观,而 history 模式不会出现 # 号,这种模式充分利用了 history.pushState() 来完成 URL 的跳转,而且无须重新加载页面。
使用 history 模式时,需要在路由规则配置中增加 mode:‘history’
var routerObj = new VueRouter({
mode: 'history',
routes: [
// 配置路由匹配规则
{path: '/nice', component: login, name: 'nice'}
]
});
5.2.2、vue-router 的基本使用
vue-router 可以实现当用户单击页面中的 A 按钮时,页面显示内容 A;单击 B 按钮时,页面显示内容 B。
需要了解路由中3个基本的概念:route、router、routes
**route:**表示它是一条路由,单数形式。
**routes:**表示它是一组路由,把 route 的每一条路由组合起来,形成一个数组 route。
**router:**它是一个机制,充当管理路由的管理者角色。
5.2.3、路由对象的属性
路由对象表示当前激活的路由的状态信息,包含了当前 URL 解析得到的信息,还有 URL 匹配到的路由记录。
路由对象是不可变的,每次成功地导航后都会产生一个新的对象。
this.$router 表示全局路由器对象,项目中通过 router 路由参数注入路由之后,在任何一个页面都可以通过此属性获取到路由器对象,并调用其 push()、go() 等方法。
$route 常用属性
属性名 | 类型 | 说明 |
---|---|---|
$route.path | String | 对应当前路由的名字,如 http://localhost/#/user?id=1,则this.$route.path 值为/user |
$route.query | Object | 一个{key:value}对象,表示URL查询参数 |
$route.params | Object | 一个{key:value}对象,路由跳转携带参数 |
$route.hash | String | 在history模式下获取当前路由的hash值,如果没有hash值,则为空字符串 |
$route.fullPath | String | 完成解析后的URL,包含查询参数和hash的完整路径 |
$route.name | String | 当前路由的名称 |
$route.matched | Array | 路由记录,当前路由下路由声明的所有信息,从父路由到当前路由为止 |
$route.redurectedFrom | String | 如果存在重定向,即为重定向来源的路由 |
5.4、动态路由
5.4.1、什么是动态路由
在 vue-router 的路由路径中,可以使用动态路径参数给路径的动态部分匹配不同的id
{path:"/user/:id", component: user}
:id,表示用户 id,它是一个动态的值。
注意,动态路由在来回切换时,由于它们都是指向同一组件,Vue 不会销毁再重新创建这个组件,而是复用这个组件。
5.4.2、query 方式传参
通过 query 方式传递参数,使用 path 属性给定对应的跳转路径,在页面跳转的时候,可以在地址栏看到请求参数。
<div id='root'>
<router-link to="/user?id=10&name=admin">登录</router-link>
<router-view></router-view>
</div>
<script>
// 定义 user 组件
var user = {
template: '<h3>id: {{$route.query.id}} name: {{$route.query.name}}</h3>',
created(){ // 组件的生命周期钩子函数
console.log(this.$route); // 用 this.$route 来接收参数
}
}
var router = new VueRouter({
routes:[
{ path:'/user', component: user}
]
});
new Vue({
el: '#root',
router,
data: {
name: '潘嘉龙'
}
})
</script>
参数值存放在 query 对象中,所以在模板中可以使用插值表达式 {{KaTeX parse error: Expected 'EOF', got '}' at position 15: route.query.id}̲} 输出 id 的值,{{route.query.name}} 输出 name 的值。
5.4.3、params 方式传参
使用 params 方式则不需要通过查询字符串传参,通常会搭配路由的 history 模式,将参数放在路径中或隐藏。
5.5、嵌套路由
5.5.1、什么是嵌套路由
嵌套路由就是在路由里面嵌套它的子路由。
当使用 children 属性实现子路由时,子路由的 path 属性前不要带 “/”,否则会永远以根路径开始请求,这样不方便用户去理解 URL 地址。
var router = new VueRouter({ // 创建路由对象
routes: [
{ path: '/', redirect: '/login'
children:[
{path: 'login', component : login},
{path: 'register', component : register},
]
},
],
mode: 'history' //使用history模式
})
5.6、命名路由
5.6.1、什么是命名路由
在创建 Router 实例的时候,在 routes 中给某个路由设置名称 name 值。
通过一个名称来标识一个路由显得更方便一些,特别是在链接一个路由,或者是执行一些跳转的时候,通过路由的名称取代路径地址直接使用。
<div id='root'>
<router-link :to="{name:'user', params:{id:123}}">登录</router-link>
<router-link :to="{path: '/user?id=' + $route.path}">登录1</router-link>
<router-view></router-view>
</div>
<script>
// 创建组件
var user = {
template: '<h3>我是user组件</h3>',
created(){
console.log(this.$route);
}
}
// 创建路由对象
const router = new VueRouter({
routes:[
{path: '/user/:id', name:'user', component: user},
{path: '/user', name:'user', component: user}
]
})
// 字符串形式
router.push('user')
// 对象形式
router.push({path: '/user'})
new Vue({
router,
el: '#root',
data: {
name: '潘嘉龙'
}
})
</script>
5.7、命名视图
5.7.1、什么是命名视图
使用 可以为视图进行命名,它主要用来负责路由跳转后组件的展示。
在 上定义 name 属性表示视图的名字,然后就可以根据不同的 name 值展示不同的页面。
<div id='root'>
<router-view></router-view>
<div class='container'>
<router-view name='left'></router-view>
<router-view name='main'></router-view>
</div>
</div>
<script>
var header = { template: '<h1 class="header">header头部区域</h1>' }
var sidebar = { template: '<h1 class="sidebar">sidebar侧导航区域</h1>' }
var mainBox = { template: '<h1 class="main">mainBox主体区域</h1>' }
const router = new VueRouter({
routes: [
{ path: '/', components: { 'default': header, 'left': sidebar, 'main': mainBox } }
]
})
new Vue({
router,
el: '#root',
data: {
name: '潘嘉龙'
}
})
</script>
5.8、编程式导航
利用 JavaScript 代码来实现地址的跳转,通过 router 实例方法来实现。
5.8.1、router.push()
使用 router.push() 方法可以导航到不同的 URL 地址。这个方法会向 history 栈添加一条新的记录,当用户单击浏览器后退按钮时,可以回到之前的 URL。
// 先获取 router 实例
var router = new VueRouter()
// 字符串形式
router.push('user')
// 对象形式
router.push({path:'/login?url=' + this.$route.paht})
// 命名路由
router.push({name: 'user', params: {userId: 123}})
// 带查询参数 /user?id=1
router.push({path:'user', query:{id:'1'}})
在参数对象中,如果提供了 path,params 会被忽略,为了传参数,需要提供路由的 name 或者手写带有参数的 path
const userId = '123'
router.push({name:'user', params:{userId}})
router.push({path:'/user/${userId}'})
// 这里的 params 不生效
router.push({path: '/user', params:{userId}})
5.8.2、router.replace()
router.replace() 方法和 router.push() 方法类似,区别在于,为 设置 replace 属性后,当单击时,就会调用 router.replace(),导航后不会向 history 栈添加新的记录,而是替换当前的 history 记录。
// 编程式
router.replace({path: 'user'})
// 声明式
<router-link :to='{path:"user"}' replace></router-link>
5.8.3、router.go()
router.go() 方法的参数是一个整数,表示在 history 历史记录中前进或后退多少步,类似于 window.history.go()。
<div id='root'>
<button @click="goBack">后退</button>
</div>
<script>
const router = new VueRouter({
})
new Vue({
router,
methods: {
goBack(){
this.$router.go(-1) //
}
},
el: '#root',
data: {
name: '潘嘉龙'
}
})
</script>