摘要:Vue Router 是 Vue.js 官网的路由管理器。它和 Vue.js 的外围深度集成,能够十分不便的用于 SPA 应用程序的开发。
本文分享自华为云社区《Vue-Router 路由疾速理解与利用》,原文作者:北极光之夜。
一. 速识概念:
1. 后端路由:
1. 依据不同的用户 URL 申请, 返回不同的内容, 实质上是 URL 申请地址与服务器资源之间的对应关系。
2. 然而呢,后端渲染存在性能问题。
2. 前端路由:
3. 所以呈现了 Ajax 前编渲染,前端渲染能进步性能,然而不反对浏览器的后退后退操作。
4. 这时又呈现了 SPA (Single Page Application)单页面应用程序,整个网站只有一个页面,内容的变动通过 Ajax 部分更新实现、同时反对浏览器地址栏的后退和后退操作。
5.SPA 实现原理之一就是基于 URL 地址的 hash (hash 的变动会导致浏览器记录拜访历史的变动、然而 hash 的变动不会触发新的 URL 申请)。在实现 SPA 过程中,其中最外围的技术点就是前端路由。
6. 前端路由就是依据不同的用户事件,显示不同的页面内容。实质就是用户事件与事件处理函数之间的对应关系。
3.Vue Router:
这是官网应用文档链接。:https://router.vuejs.org/zh/g…
Vue Router 是 Vue.js 官网的路由管理器。它和 Vue.js 的外围深度集成,能够十分不便的用于 SPA 应用程序的开发。
它的性能如下:
1. 反对 HTML5 历史模式或 hash 模式。
2. 反对嵌套路由。
3. 反对路由参数。
4. 反对编程式路由。
5. 反对命名路由。
二. 根本应用:
前提:
上面将会以一个 HTML 单页面演示 Vue Router 的根本应用步骤。在 vue 我的项目里也是一样的原理。以后单页面根本代码:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app">
</div>
<script>
const app = new Vue({
el:"#app",
data: {}})
</script>
</body>
</html>
能够看到什么都没有:
上面开始应用的具体步骤:
1. 引入相干的文件:
单页面必定得先导入 vue 文件与 vue-router 文件,这样咱们才可能应用路由。
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
2. 增加路由链接:
以下是一个 vue 提供的标签,默认会被渲染为 a 标签。其中有一个 to 属性,这个 to 属性会被渲染为 href 属性,默认值被渲染为 # 结尾的 hash 地址。简略来说就是当用户点击不同时跳转不同内容,而这个标签就是用户要点击的货色,相当于 a 标签嘛。
<router-link to="/..." >...</router-link>
给咱们的单页面上加一个 page1 和一个 page2 的链接:
<div id="app">
<router-link to="/page1">Page1</router-link>
<router-link to="/page2">Page2</router-link>
</div>
3. 增加路由填充位:
上面这个标签叫路由填充位,就是说将来通过咱们的路由规定匹配到的组件,将会被渲染到 router-view 所在位置。简略来说,就是用户点击路由链接,那得跳转内容吧,咱们晓得的是必定不是整个页面都跳转,只是页面内相干的部分产生内容扭转,这个部分就是 router-view 所在显示的区域。
<router-view></router-view>
给咱们的页面增加:
<div id="app">
<router-link to="/page1">Page1</router-link>
<router-link to="/page2">Page2</router-link>
<router-view></router-view>
</div>
4. 定义路由组件:
既然要显示不同的内容,那必定是用一个组件保留一份内容。上面咱们给单页面定义 page1,page2 这两个组件。
<script>
const Page1 = {template: '<h1> 我是北极光之夜 1 号 </h1>'}
const Page2 = {template: '<h1> 我是北极光之夜 2 号 </h1>'}
const app = new Vue({
el:"#app",
data: {}})
</script>
5. 配置路由规定井创立路由实例:
routes 是路由规定数组。每个路由规定都是一个配置对象,其中至多蕴含 path 和 component 两个属性,path 示意以后路由规定匹配的 hash 地址,component 示意以后路由规定对应要展现的组件。简略来说就是你点击那个链接对应的地址要对应的是哪个内容的组件。path 跟 router-link 标签里的地址要一样,别写错了。
const router = new VueRouter({
routes: [{path:'/page1',component:Page1},
{path:'/page2',component:Page2}
]
})
6. 把路由挂载到 Vue 根实例中:
为了可能让路由规定失效,必须把路由对象挂载到 vue 实例对象上。
const app = new Vue({
el:"#app",
data: {},
router
})
7. 成果与单页面代码:
以上咱们就大工告成~
下面的残缺代码:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<!-- 导入 vue 文件 -->
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
</head>
<body>
<div id="app">
<router-link to="/page1">Page1</router-link>
<router-link to="/page2">Page2</router-link>
<router-view></router-view>
</div>
<script>
const Page1 = {template: '<h1> 我是北极光之夜 1 号 </h1>'}
const Page2 = {template: '<h1> 我是北极光之夜 2 号 </h1>'}
const router = new VueRouter({
routes: [{path:'/page1',component:Page1},
{path:'/page2',component:Page2}
]
})
const app = new Vue({
el:"#app",
data: {},
router
})
</script>
</body>
</html>
三. 路由重定向:
路由重定向指的是用户在拜访地址 A 的时候, 强制用户跳转到地址 B,从而展现特定的组件页面。
通过路由规定的 redirect 属性, 指定一个新的路由地址,能够很不便地设置路由的重定向。
{path:'/..',redirect: '/...'}
其中 path 示意重定向的原地址,redirect 示意新地址。
比方第二大点的案例中,刚关上的页面如下,在根目录,但咱们想一进入就显示 page1,那就给根目录重定向。
批改路由规定如下:
const router = new VueRouter({
routes: [{path:'/page1',component:Page1},
{path:'/page2',component:Page2},
{path:'/',redirect:'/page1'}
]
})
看成果,我没点击就默认进入 page1 了:
四. 嵌套路由:
性能如下:
- 点击父级路由链接显示模板内容。
- 模板内容中又有子级路由链接。
- 点击子级路由链接显示子级模板内容。
比方咱们改良第二大点的案例,当点击 page2 显示 page2 内容时,page2 里又有两个子路由连贯,star 和 moon,当点击其中一个链接时又能显示对应的 star 或 moon 内容。
1. 首先给 page2 组件增加两个子路由链接:
const Page2 = {
template: `
<div>
<h1> 我是北极光之夜 2 号 </h1>
<hr/>
<router-link to="/page2/star">Star</router-link>
<router-link to="/page2/moon">Moon</router-link>
<hr/>
</div>`
}
此时页面也把显示子路由链接进去了:
2. 给两个子路由链接增加路由填充位:
const Page2 = {
const Page2 = {
template: `
<div>
<h1> 我是北极光之夜 2 号 </h1>
<hr/>
<router-link to="/page2/star">Star</router-link>
<router-link to="/page2/moon">Moon</router-link>
<hr/>
<router-view></router-view>
</div>`
}
3. 设置两个子组件 star 与 moon 的内容:
const Star = {template: '<h2> 我是北极光之夜 2 号下的 star</h2>'}
const Moon = {template: '<h2> 我是北极光之夜 2 号下的 Moon</h2>'}
4. 配置路由规定:
page2 的规定除了 path 和 component 属性外,再增加一个 children 属性,这个属性以数组示意,数组里寄存其子路由的规定,其规定也是一样的,套娃套娃。
const router = new VueRouter({
routes: [{path:'/page1',component:Page1},
{
path:'/page2',
component:Page2,
children: [{path: '/page2/star',component:Star},
{path: '/page2/moon',component:Moon}
]
}
]
})
5. 成果与单页面代码:
残缺代码:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<!-- 导入 vue 文件 -->
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
</head>
<body>
<div id="app">
<router-link to="/page1">Page1</router-link>
<router-link to="/page2">Page2</router-link>
<router-view></router-view>
</div>
<script>
const Page1 = {template: '<h1> 我是北极光之夜 1 号 </h1>'}
const Page2 = {
template: `
<div>
<h1> 我是北极光之夜 2 号 </h1>
<hr/>
<router-link to="/page2/star">Star</router-link>
<router-link to="/page2/moon">Moon</router-link>
<hr/>
<router-view></router-view>
</div>`
}
const Star = {template: '<h2> 我是北极光之夜 2 号下的 star</h2>'}
const Moon = {template: '<h2> 我是北极光之夜 2 号下的 Moon</h2>'}
const router = new VueRouter({
routes: [{path:'/page1',component:Page1},
{
path:'/page2',
component:Page2,
children: [{path: '/page2/star',component:Star},
{path: '/page2/moon',component:Moon}
]
}
]
})
const app = new Vue({
el:"#app",
data: {},
router
})
</script>
</body>
</html>
五. 动静路由匹配:
1. 动静匹配路由根本应用:
如果某些路由规定的一部分是一样的,只有另一部分是动态变化的,那咱们能够把这些动态变化的局部造成路由参数,这些参数就叫做动静路由匹配。简略来说,你先看上面这些路由链接,它们都有 /page/,就是前面不一样:
<router-link to="/page/1">Page1</router-link>
<router-link to="/page/2">Page2</router-link>
<router-link to="/page/3">Page3</router-link>
那该咋配置路由呢?这样吗:
const router = new VueRouter({
routes: [{path:'/page/1',component:Page},
{path:'/page/2',component:Page},
{path:'/page/3',component:Page}
]
})
这样万一有很多一个个写岂不是太麻烦了,所以引入参数,在动静扭转的局部定义为参数,参数后面有一个冒号, 那下面可简写成如下,动静局部设为参数:id。
const router = new VueRouter({
routes: [{path:'/page/:id',component:Page},
]
})
在组件能够通过以下语法获取以后路由的参数:
$router.params. 参数名称
好,再次批改第二大点的案例实现动静路由匹配:
1. 定义路由链接:
<div id="app">
<router-link to="/page/1">Page1</router-link>
<router-link to="/page/2">Page2</router-link>
<router-link to="/page/3">Page3</router-link>
<router-view></router-view>
</div>
2. 动静配置路由,参数 id:
const router = new VueRouter({
routes: [{path:'/page/:id',component:Page1},
]
})
3. 设置组件内容,并显示以后路由的参数:
const Page1 = {template: '<h1> 我是北极光之夜 1 号, 以后 id 为:{{$route.params.id}}</h1>'
}
看成果:
2. 路由组件传参:
下面的 $route 与对应路由造成高度耦合,不够灵便啊,所以能够应用 props 将组件和路由解耦。简略来说,如同也没什么说的,间接看上面实例就能了解了。
2.1 当 props 为布尔类型:
const router = new VueRouter({
routes: [
// 设置 props,如果 props 为 true,router.params 会被设置为组件属性
{path:'/page/:id',component:Page1,props: true},
]
})
const Page1 = {
// 这时就通过 props 接管参数,疾速简洁的接管参数 id 和应用它
props: ['id'],
template: '<h1> 我是北极光之夜 1 号, 以后 id 为:{{id}}</h1>'
}
能达到一样的成果,且更灵便了,下面记得反过来,先定义组件才配置路由规定,只是为了直观才这样写:
2.2 当 props 为对象类型:
const Page1 = {
// 这时就通过 props 接管参数,疾速简洁的接管参数对象 并显示
props: ['name','age'],
template: `<h1> 我是北极光之夜 1 号, 以后 id 为:{{id}}
<hr/>
姓名为:{{name}},年龄为:{{age}} </h1>`
}
const router = new VueRouter({
routes: [
// props 为一个参数对象,它会原样设置为组件属性,// 外面的自定义的参数都能传过来,然而 id 传不了了
{path:'/page/:id',component:Page1 , props: {name:'auroras',age: 18} }
]
})
成果,对象 props 对象里的能获取,id 就不行了:
2.3 当 props 为函数类型:
这个就什么都能获取。
const Page1 = {
// 这时就通过 props 接管参数,疾速简洁的接管参数
props: ['name','age','id'],
template: `<h1> 我是北极光之夜 1 号, 以后 id 为:{{id}}
<hr/>
姓名为:{{name}},年龄为:{{age}} </h1>`
}
const router = new VueRouter({
routes: [
// props 为函数,这个对象接管 router 对象为本人形参,// 外面的自定义的参数和 id 都能传过来
{path:'/page/:id',
component:Page1 ,
props: router => ({id: router.params.id,name:'auroras',age: 18}) }
]
})
成果:
以后残缺代码:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<!-- 导入 vue 文件 -->
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
</head>
<body>
<div id="app">
<router-link to="/page/1">Page1</router-link>
<router-link to="/page/2">Page2</router-link>
<router-link to="/page/3">Page3</router-link>
<router-view></router-view>
</div>
<script>
const Page1 = {
// 这时就通过 props 接管参数,疾速简洁的接管参数对象
props: ['name','age','id'],
template: `<h1> 我是北极光之夜 1 号, 以后 id 为:{{id}}
<hr/>
姓名为:{{name}},年龄为:{{age}} </h1>`
}
const router = new VueRouter({
routes: [
// props 为函数,这个对象接管 router 对象为本人形参,// 外面的自定义的参数和 id 都能传过来
{path:'/page/:id',
component:Page1 ,
props: router => ({id: router.params.id,name:'auroras',age: 18}) }
]
})
const app = new Vue({
el:"#app",
data: {},
router
})
</script>
</body>
</html>
六.Vue-Router 命名路由:
为更加不便的示意路由的门路,能够给路由规定起一个别名,即为“命名路由”。持续改良下面的案例解说用法:
1. 首先给路由规定加一个 name 属性,这个就是别名:
const router = new VueRouter({
routes: [
{
name: 'user',
path:'/page/:id',
component:Page1 ,
props: router => ({id: router.params.id,name:'auroras',age: 18}) }
]
})
2. 在路由链接中应用:
<div id="app">
<router-link :to="{name:'user',params: {id: 1}}">Page1</router-link>
<router-link to="/page/2">Page2</router-link>
<router-link to="/page/3">Page3</router-link>
<router-view></router-view>
</div>
咱们把第一个路由链接改良,to 后面加上冒号,其中 name 示意匹配的是哪个路由规定,params 示意要传递的参数,看上面是一样的成果:
七. 编程式导航:
- 申明式导航:首先申明式导航是指用户通过点击链接实现导航的形式,比方点击 a 标签或者路由链接这些实现的跳转。
- 编程式导航:编程式导航就是说跳转是因为我点击它,它不是链接,然而它在 JavaScript 里调用了某个 API 也实现了跳转。
- 罕用的编程式导航 API 如下:
this.$router.push('要跳转的 hash 地址')
this.$router.go(n)
push 里间接放要跳转的哈希地址,go 办法实现后退和后退,n 代表数组,若 n 为 1 代表在历史记录中后退一位,- 1 代表在历史记录中后退一位。
1. this.$router.push(’‘):
重写一个案例,有 page1、page2、page3 三个路由链接,而在 page3 里有一个按钮,这个按钮的作用是点击后返回显示 page1 的内容。这个按钮可不是申明式导航里的链接,就是一个按钮。
1. 定义一般的路由链接:
<div id="app">
<router-link :to="/page/1">Page1</router-link>
<router-link to="/page/2">Page2</router-link>
<router-link to="/page/3">Page3</router-link>
<router-view></router-view>
</div>
2. 定义 3 个组件内容,其中给 page3 组件里放一个按钮,并绑定点击事件,在事件里通过 API 导航到 page1:
const Page1 = {template: `<h1> 我是北极光之夜 1 号 </h1>`}
const Page2 = {template: `<h1> 我是北极光之夜 2 号 </h1>`}
const Page3 = {
template: `<div>
<h1> 我是北极光之夜 3 号 </h1>
<button @click="goPage1"> 返回 page1</button>
</div>`,
methods: {goPage1(){this.$router.push('/page/1')
}
},
}
3. 路由规定:
const router = new VueRouter({
routes: [{path:'/page/1',component: Page1},
{path:'/page/2',component: Page2},
{path:'/page/3',component: Page3}
]
})
4. 看成果:
5. 残缺代码:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<!-- 导入 vue 文件 -->
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
</head>
<body>
<div id="app">
<router-link to="/page/1">Page1</router-link>
<router-link to="/page/2">Page2</router-link>
<router-link to="/page/3">Page3</router-link>
<router-view></router-view>
</div>
<script>
const Page1 = {template: `<h1> 我是北极光之夜 1 号 </h1>`}
const Page2 = {template: `<h1> 我是北极光之夜 2 号 </h1>`}
const Page3 = {
template: `<div>
<h1> 我是北极光之夜 3 号 </h1>
<button @click="goPage1"> 返回 page1</button>
</div>`,
methods: {goPage1(){this.$router.push('/page/1')
}
},
}
const router = new VueRouter({
routes: [{path:'/page/1',component: Page1},
{path:'/page/2',component: Page2},
{path:'/page/3',component: Page3}
]
})
const app = new Vue({
el:"#app",
data: {},
router
})
</script>
</body>
</html>
不止 href 门路,还能够有以下操作:
// 字符串模式(门路的名称)router.push('/page1')
// 对象的模式
router.push({path: '/page1'})
// 也能够传递参数,命名的路由
router.push({name: '/page1',parmas:{id: 1}})
// 带查问参数,变成 /page1?p=id
// 这个挺实用的,比方在某些音乐网页,点击歌单后要导航到另一个该歌单具体界面,此时要带 id,具体界面靠此 id 从新发送申请,申请详细信息
router.push({parh: '/page1',query:{p: 'id'}})
2. this.$router.go(n):
改良第 1 小点的案例,当我 page3 跳到 page1 时,page1 里又有一个返回的按钮。咱们把 n 设置为 -1,他就会在历史记录中后退一位,后退一位就是 page3.
批改 page1 组件内容:
const Page1 = {
template: `<div>
<h1> 我是北极光之夜 1 号 </h1>
<button @click="goBack"> 返回 </button>
</div>`,
methods: {goBack(){this.$router.go(-1)
}
}
}
成果:
点击关注,第一工夫理解华为云陈腐技术~