vue-router是Vue.js官方的路由插件,它和vue.js是深度集成的,适合用于构建单页面应用。vue的单页面应用是基于路由和组件的,路由用于设定访问路径,并将路径和组件映射起来。传统的页面应用,是用一些超链接来实现页面切换和跳转的。在vue-router单页面应用中,则是路径之间的切换,也就是组件的切换。
本文将以示例的形式来介绍vue-router的各个特性,一共包含6个示例,每个示例都有乞丐版,前5个示例有皇帝版。
乞丐版是将所有代码混杂在一起的HTML页面,皇帝版是基于vue-webpack-simple模板构建的。
乞丐版可以让你快速地了解到vue-router的一些特性和API;皇帝版则基于.vue组件和单独的路由配置,更适用于实际的应用。
本文的Demo和源代码已放到GitHub,如果您觉得内容不错,请点个赞,或在GitHub上加个星星!
第一个单页面应用 嵌套路由示例 具名路径示例 路由对象示例 让链接处于选中状态示例 钩子函数示例 GitHub Source
在GitHub上,乞丐版和皇帝版的目录结构如下:
├─06.Router // vue-router示例目录 │ ├─basic // 乞丐版示例 │ ├──basic_01.html // 第一个单页面应用 │ ├──basic_02.html // 嵌套路由示例 │ ├──basic_03.html // 具名路径示例 │ ├──basic_04.html // 路由对象实例 │ ├──basic_05.html // 让链接处于选中状态示例 │ ├──basic_06.html // 钩子函数示例 │ ├─demo01 // 皇帝版,和basic_01.html对应 │ ├─demo02 // 皇帝版,和basic_02.html对应 │ ├─demo03 // 皇帝版,和basic_03.html对应 │ ├─demo04 // 皇帝版,和basic_04.html对应 │ ├─demo05 // 皇帝版,和basic_05.html对应
第一个单页面应用(01)
现在我们以一个简单的单页面应用开启vue-router之旅,这个单页面应用有两个路径:/home和/about,与这两个路径对应的是两个组件Home和About。
1. 创建组件
首先引入vue.js和vue-router.js:
<script src="js/vue.js"></script>
<script src="js/vue-router.js"></script>
然后创建两个组件构造器Home和About:
var Home = Vue.extend({
template: '<div><h1>Home</h1><p>{{msg}}</p></div>',
data: function() {
return {
msg: 'Hello, vue router!'
}
}
})
var About = Vue.extend({
template: '<div><h1>About</h1><p>This is the tutorial about vue-router.</p></div>'
})
2. 创建Router
var router = new VueRouter()
调用构造器VueRouter,创建一个路由器实例router。
3. 映射路由
router.map({
'/home': { component: Home },
'/about': { component: About }
})
调用router的map方法映射路由,每条路由以key-value的形式存在,key是路径,value是组件。
例如:'/home'是一条路由的key,它表示路径;{component: Home}则表示该条路由映射的组件。
4. 使用v-link指令
<div class="list-group">
<a class="list-group-item" v-link="{ path: '/home'}">Home</a>
<a class="list-group-item" v-link="{ path: '/about'}">About</a>
</div>
在a元素上使用v-link指令跳转到指定路径。
5. 使用<router-view>标签
<router-view></router-view>
在页面上使用<router-view></router-view>标签,它用于渲染匹配的组件。
6. 启动路由
var App = Vue.extend({})
router.start(App, '#app')
路由器的运行需要一个根组件,router.start(App, '#app') 表示router会创建一个App实例,并且挂载到#app元素。
注意:使用vue-router的应用,不需要显式地创建Vue实例,而是调用start方法将根组件挂载到某个元素。
7. 完整代码
1 <!DOCTYPE html> 2 <html> 3 4 <head> 5 <meta charset="UTF-8"> 6 <title>vue-router--第一个单页面应用(01)</title> 7 <link rel="stylesheet" href="../js/bootstrap.css"> 8 <script src="../js/vue.js"></script> 9 <script src="../js/vue-router.js"></script> 10 </head> 11 12 <body> 13 <div id="app"> 14 <div class="row"> 15 <div class="col-xs-offset-2 col-xs-8"> 16 <div class="page-header"> 17 <h2>Router Basic - 01</h2> 18 </div> 19 </div> 20 </div> 21 <div class="row"> 22 <div class="col-xs-2 col-xs-offset-2"> 23 <div class="list-group"> 24 <!--使用指令v-link进行导航--> 25 <a class="list-group-item" v-link="{ path: '/home'}">Home</a> 26 <a class="list-group-item" v-link="{ path: '/about'}">About</a> 27 </div> 28 </div> 29 <div class="col-xs-6"> 30 <div class="panel"> 31 <div class="panel-body"> 32 <!--用于渲染匹配的组件--> 33 <router-view></router-view> 34 </div> 35 </div> 36 </div> 37 </div> 38 </div> 39 <template id="home"> 40 <div> 41 <h1>Home</h1> 42 <p>{{msg}}</p> 43 </div> 44 </template> 45 <template id="about"> 46 <div> 47 <h1>About</h1> 48 <p>This is the tutorial about vue-router.</p> 49 </div> 50 </template> 51 </body> 52 <script> 53 /* 创建组件构造器 */ 54 var Home = Vue.extend({ 55 template: '#home', 56 data: function() { 57 return { 58 msg: 'Hello, vue router!' 59 } 60 } 61 }) 62 63 var About = Vue.extend({ 64 template: '#about' 65 }) 66 67 /* 创建路由器 */ 68 var router = new VueRouter() 69 70 /* 创建路由映射 */ 71 router.map({ 72 '/home': { 73 component: Home 74 }, 75 '/about': { 76 component: About 77 } 78 }) 79 80 router.redirect({ 81 '/': '/home' 82 }) 83 84 /* 启动路由 */ 85 var App = Vue.extend({}) 86 router.start(App, '#app') 87 </script> 88 89 </html>
当你从GitHub上获取到最新的源代码后,如果想运行皇帝版,以demo01为例,在Git Bash下执行以下命令:
npm run demo01-dev
然后在浏览器中访问地址http://127.0.0.1:8080
如果要编译和发布,请在Git Bash下执行以下命令:
npm run demo01-build
编写单页面的步骤
上面的6个步骤,可以说是创建一个单页面应用的基本步骤:
JavaScript
- 创建组件:创建单页面应用需要渲染的组件
- 创建路由:创建VueRouter实例
- 映射路由:调用VueRouter实例的map方法
- 启动路由:调用VueRouter实例的start方法
HTML
- 使用v-link指令
- 使用<router-view>标签
router.redirect
应用在首次运行时右侧是一片空白,应用通常都会有一个首页,例如:Home页。
使用router.redirect方法将根路径重定向到/home路径:
router.redirect({
'/': '/home'
})
router.redirect方法用于为路由器定义全局的重定向规则,全局的重定向会在匹配当前路径之前执行。
执行过程
当用户点击v-link指令元素时,我们可以大致猜想一下这中间发生了什么事情:
- vue-router首先会去查找
v-link指令的路由映射 - 然后根据路由映射找到匹配的组件
- 最后将组件渲染到
<router-view>标签
嵌套路由(02)
嵌套路由是个常见的需求,假设用户能够通过路径/home/news和/home/message访问一些内容,一个路径映射一个组件,访问这两个路径也会分别渲染两个组件。
实现嵌套路由有两个要点:
- 在组件内部使用
<router-view>标签 - 在路由器对象中给组件定义子路由
现在我们就动手实现这个需求。
组件模板:
<template id="home">
<div>
<h1>Home</h1>
<p>{{msg}}</p>
</div>
<div>
<ul class="nav nav-tabs">
<li>
<a v-link="{ path: '/home/news'}">News</a>
</li>
<li>
<a v-link="{ path: '/home/message'}">Messages</a>
</li>
</ul>
<router-view></router-view>
</div>
</template>
<template id="news">
<ul>
<li>News 01</li>
<li>News 02</li>
<li>News 03</li>
</ul>
</template>
<template id="message">
<ul>
<li>Message 01</li>
<li>Message 02</li>
<li>Message 03</li>
</ul>
</template>
组件构造器:
var Home = Vue.extend({
template: '#home',
data: function() {
return {
msg: 'Hello, vue router!'
}
}
})
var News = Vue.extend({
template: '#news'
})
var Message = Vue.extend({
template: '#message'
})
路由映射:
router.map({
'/home': {
component: Home,
// 定义子路由
subRoutes: {
'/news': {
component: News
},
'/message': {
component: Message
}
}
},
'/about': {
component: About
}
})
在/home路由下定义了一个subRoutes选项,/news和/message是两条子路由,它们分别表示路径/home/news和/home/message,这两条路由分别映射组件News和Message。
完整代码
1 <!DOCTYPE html> 2 <html> 3 4 <head> 5 <meta charset="UTF-8"> 6 <title>vue-router嵌套路由(02)</title> 7 <link rel="stylesheet" href="../js/bootstrap.css"> 8 <script src="../js/vue.js"></script> 9 <script src="../js/vue-router.js"></script> 10 </head> 11 12 <body> 13 <div id="app"> 14 <div class="row"> 15 <div class="col-xs-offset-2 col-xs-8"> 16 <div class="page-header"> 17 <h2>Router Basic - 02</h2> 18 </div> 19 </div> 20 </div> 21 <div class="row"> 22 <div class="col-xs-2 col-xs-offset-2"> 23 <div class="list-group"> 24 <a class="list-group-item" v-link="{ path: '/home'}">Home</a> 25 <a class="list-group-item" v-link="{ path: '/about'}">About</a> 26 </div> 27 </div> 28 <div class="col-xs-6"> 29 <div class="panel"> 30 <div class="panel-body"> 31 <router-view></router-view> 32 </div> 33 </div> 34 </div> 35 </div> 36 </div> 37 38 <template id="home"> 39 <div> 40 <h1>Home</h1> 41 <p>{{msg}}</p> 42 </div> 43 <div> 44 <ul class="nav nav-tabs"> 45 <li> 46 <a v-link="{ path: '/home/news'}">News</a> 47 </li> 48 <li> 49 <a v-link="{ path: '/home/message'}">Messages</a> 50 </li> 51 </ul> 52 <router-view></router-view> 53 </div> 54 </template> 55 56 <template id="news"> 57 <ul> 58 <li>News 01</li> 59 <li>News 02</li> 60 <li>News 03</li> 61 </ul> 62 </template> 63 <template id="message"> 64 <ul> 65 <li>Message 01</li> 66 <li>Message 02</li> 67 <li>Message 03</li> 68 </ul> 69 </template> 70 71 <template id="about"> 72 <div> 73 <h1>About</h1> 74 <p>This is the tutorial about vue-router.</p> 75 </div> 76 </template> 77 78 </body> 79 <script> 80 var Home = Vue.extend({ 81 template: '#home', 82 data: function() { 83 return { 84 msg: 'Hello, vue router!' 85 } 86 } 87 }) 88 89 var News = Vue.extend({ 90 template: '#news' 91 }) 92 93 var Message = Vue.extend({ 94 template: '#message' 95 }) 96 97 var About = Vue.extend({ 98 template: '#about' 99 }) 100 101 var router = new VueRouter() 102 router.redirect({ 103 '/': '/home' 104 }) 105 router.map({ 106 '/home': { 107 component: Home, 108 // 定义子路由 109 subRoutes: { 110 '/news': { 111 component: News 112 }, 113 '/message': { 114 component: Message 115 } 116 } 117 }, 118 '/about': { 119 component: About 120 } 121 }) 122 123 var App = Vue.extend({}) 124 router.start(App, '#app') 125 </script> 126 127 </html>