Vue学习笔记(5):VueRouter

(下面基于vue2来讲解)

官方介绍:

用 Vue.js + Vue Router 创建单页应用,感觉很自然:使用 Vue.js ,我们已经可以通过组合组件来组成应用程序,当你要把 Vue Router 添加进来,我们需要做的是,将组件 (components) 映射到路由 (routes),然后告诉 Vue Router 在哪里渲染它们。

简单例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>

<div id="app">
<h1>Hello App!</h1>
<p>
<!-- 使用 router-link 组件来导航. -->
<!-- 通过传入 `to` 属性指定链接. -->
<!-- <router-link> 默认会被渲染成一个 `<a>` 标签 -->
<router-link to="/foo">Go to Foo</router-link>
<router-link to="/bar">Go to Bar</router-link>
</p>
<!-- 路由出口 -->
<!-- 路由匹配到的组件将渲染在这里 -->
<router-view></router-view>
</div>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
// 0. 如果使用模块化机制编程,导入Vue和VueRouter,要调用 Vue.use(VueRouter)

// 1. 定义 (路由) 组件。
// 可以从其他文件 import 进来
const Foo = { template: '<div>foo</div>' }
const Bar = { template: '<div>bar</div>' }

// 2. 定义路由
// 每个路由应该映射一个组件。 其中"component" 可以是
// 通过 Vue.extend() 创建的组件构造器,
// 或者,只是一个组件配置对象。
// 我们晚点再讨论嵌套路由。
const routes = [
{ path: '/foo', component: Foo },
{ path: '/bar', component: Bar }
]

// 3. 创建 router 实例,然后传 `routes` 配置
// 你还可以传别的配置参数, 不过先这么简单着吧。
const router = new VueRouter({
routes // (缩写) 相当于 routes: routes
})

// 4. 创建和挂载根实例。
// 记得要通过 router 配置参数注入路由,
// 从而让整个应用都有路由功能
const app = new Vue({
router
}).$mount('#app')

// 现在,应用已经启动了!

在线演示

动态路由匹配

简单来说就是通过路由传递参数,比如路由url设置:’/user/:name’,当访问:’/user/foo’的时候将会映射到这个路由,然后在被调用的组件里通过$router.params.name获取到’foo’。

演示代码如下:

1
2
3
4
5
6
7
8
9
10
const User = {
template: '<div>User {{ $route.params.id }}</div>'
}

const router = new VueRouter({
routes: [
// 动态路径参数 以冒号开头
{ path: '/user/:id', component: User }
]
})

在线演示

除此之外还可与设置多端的参数,比如模式:’/user/:username/post/:post_id’,通过:’/user/evan/post/123’可以匹配到:{ username: 'evan', post_id: '123' }

响应路由参数的变化

当匹配的模式不改变,只改变参数时,已经渲染的组件不会再次渲染,也就是各种钩子函数也不会生效,可以使用watch监听参数的变化:

1
2
3
4
5
6
7
8
const User = {
template: '...',
watch: {
$route(to, from) {
// 对路由变化作出响应...
}
}
}

或者使用 2.2 中引入的 beforeRouteUpdate 导航守卫:

1
2
3
4
5
6
7
const User = {
template: '...',
beforeRouteUpdate(to, from, next) {
// react to route changes...
// don't forget to call next()
}
}

捕获所有路由或 404 Not found 路由

常规参数只会匹配被 / 分隔的 URL 片段中的字符。如果想匹配任意路径,我们可以使用通配符 ().
当使用通配符路由时,请确保路由的顺序是正确的,也就是说含有通配符的路由应该放在最后。路由 { path: ‘
‘ } 通常用于客户端 404 错误。如果你使用了History 模式,请确保正确配置你的服务器。

也就是说,如果我们需要做一个404 Not Found 页面的话,可以这样:

1
2
3
4
5
6
7
8
9
10
const NotFoundPage = {
template: '<div>404 Not Found!</div>'
}

const router = new VueRouter({
routes: [
// 动态路径参数 以冒号开头
{ path: '*', component: NotFoundPage }
]
})

这样当跳转到路由没定义的url就会匹配上这一条规则。

高级匹配模式

vue-router 使用 path-to-regexp (opens new window)作为路径匹配引擎,所以支持很多高级的匹配模式,例如:可选的动态路径参数、匹配零个或多个、一个或多个,甚至是自定义正则匹配。

下面是官方推荐的例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)
// The matching uses path-to-regexp, which is the matching engine used
// by express as well, so the same matching rules apply.
// For detailed rules, see https://github.com/pillarjs/path-to-regexp
const router = new VueRouter({
mode: 'history',
base: __dirname,
routes: [
{ path: '/' },
// params are denoted with a colon ":"
{ path: '/params/:foo/:bar' },
// a param can be made optional by adding "?"
{ path: '/optional-params/:foo?' },
// a param can be followed by a regex pattern in parens
// this route will only be matched if :id is all numbers
{ path: '/params-with-regex/:id(\\d+)' },
// asterisk can match anything
{ path: '/asterisk/*' },
// make part of the path optional by wrapping with parens and add "?"
{ path: '/optional-group/(foo/)?bar' }
]
})

new Vue({
router,
template: `
<div id="app">
<h1>Route Matching</h1>
<ul>
<li><router-link to="/">/</router-link></li>
<li><router-link to="/params/foo/bar">/params/foo/bar</router-link></li>
<li><router-link to="/optional-params">/optional-params</router-link></li>
<li><router-link to="/optional-params/foo">/optional-params/foo</router-link></li>
<li><router-link to="/params-with-regex/123">/params-with-regex/123</router-link></li>
<li><router-link to="/params-with-regex/abc">/params-with-regex/abc</router-link></li>
<li><router-link to="/asterisk/foo">/asterisk/foo</router-link></li>
<li><router-link to="/asterisk/foo/bar">/asterisk/foo/bar</router-link></li>
<li><router-link to="/optional-group/bar">/optional-group/bar</router-link></li>
<li><router-link to="/optional-group/foo/bar">/optional-group/foo/bar</router-link></li>
</ul>
<p>Route context</p>
<pre>{{ JSON.stringify($route, null, 2) }}</pre>
</div>
`
}).$mount('#app')

匹配优先级

路由定义的优先级:路由定义得越早,优先级就越高