vue-router是Vue.js官方的路由插件,适合用于构建单页面应用。
vue的单页面应用是基于路由和组件的,路由用于设定访问路径,并将路径和组件映射起来。
配置vue-router总共分以下几步:
页面中使用
,路由匹配到的组件将渲染在这里。
<div id="app">
<router-view>router-view>
div>
上面例子中的router-view是最顶层的出口,渲染最高级路由匹配到的组件。
但是同时一个被渲染的组件同样可以包含自己的router-view。
const User = {
template: `
<div class="user">
<h2>User {
{ $route.params.id }}h2>
<router-view>router-view>
div>
`
}
具体嵌套路由如何配置可以参考定义路由。
我们要通过生成一个VueRouter的实例来生成路由:
var router = new VueRouter({
//options
})
其中要给构造函数中传入options对象来配置路由。
通常options对象由以下几部分组成:
是一个数组,定义将要使用的路由们。
每一个路由有以下几个常用配置:
{
path:路径,
component:路由映射的组件,
name:命名路由,
children:嵌套路由,
components:针对命名视图,
redirect:重定向
}
因此我们可以这样定义路由:
const routes = [
{ path: '/foo', component: Foo },
{ path: '/bar', component: Bar }
]
但有时候我们可能想把某种模式匹配到的所有路由都映射到同一个组件,这时候就可以在路由路径中使用动态路径参数:
const router = new VueRouter({
routes:[
{path:'/user/:id',component:User}
]
})
这样,像 /user/foo 和 /user/bar 都将映射到相同的路由。
一个『路径参数』使用冒号 : 标记。当匹配到一个路由时,参数值会被设置到 this.$route.params,可以在每个组件内使用。
比如在User组件内,我们就可以获取到当前的参数:
const User = {
template: '<div>User {
{ $route.params.id }}div>'
}
当使用路由参数时,例如从 /user/foo 导航到 user/bar,原来的组件实例会被复用。因为两个路由都渲染同个组件,比起销毁再创建,复用则显得更加高效。
不过,这也意味着组件的生命周期钩子不会再被调用。
复用组件时,想对路由参数的变化作出响应的话,可以watch $route 对象:
const User = {
template: '...',
watch: {
'$route' (to, from) {
// 对路由变化作出响应...
}
}
}
针对一开始提到的嵌套路由:
<div id="app">
<router-view>router-view>
div>
const User = {
template: `
<div class="user">
<h2>User {
{ $route.params.id }}h2>
<router-view>router-view>
div>
`
}
想要在User组件内的路由出口中渲染组件,必须要使用children配置:
const router = new VueRouter({
routes: [
{ path: '/user/:id', component: User,
children: [
{
// 当 /user/:id/profile 匹配成功,
// UserProfile 会被渲染在 User 的 中
path: 'profile',
component: UserProfile
},
{
// 当 /user/:id/posts 匹配成功
// UserPosts 会被渲染在 User 的 中
path: 'posts',
component: UserPosts
}
]
}
]
})
要注意,以 / 开头的嵌套路径会被当作根路径。 这让你充分的使用嵌套组件而无须设置嵌套的路径。
你会发现,children 配置就是像 routes 配置一样的路由配置数组,所以呢,你可以嵌套多层路由。
有时候想同时展示多个视图,而不是嵌套展示,例如创建一个布局,有 sidebar 和 main 两个视图,这个时候命名视图就派上用场了。
你可以在界面中拥有多个单独命名的视图,而不是只有一个单独的出口。如果 router-view 没有设置名字,那么默认为 default。
<router-view class="view one">router-view>
<router-view class="view two" name="a">router-view>
<router-view class="view three" name="b">router-view>
一个视图使用一个组件渲染,因此对于同个路由,多个视图就需要多个组件。确保正确使用 components 配置(注意此时是复数形式的哦!)
const router = new VueRouter({
routes: [
{
path: '/',
components: {
default: Foo,
a: Bar,
b: Baz
}
}
]
})
路由的重定向也是通过routes配置来完成的:
const router = new VueRouter({
routes: [
{ path: '/a', redirect: '/b' }
]
})
重定向的目标也可以是一个命名的路由:
const router = new VueRouter({
routes: [
{ path: '/a', redirect: { name: 'foo' }}
]
})
『重定向』的意思是,当用户访问 /a时,URL 将会被替换成 /b,然后匹配路由为 /b。
别名的意思则是,/a 的别名是 /b,意味着,当用户访问 /b 时,URL 会保持为 /b,但是路由匹配则为 /a。
可以通过alias属性配置路由的别名:
const router = new VueRouter({
routes: [
{ path: '/a', component: A, alias: '/b' }
]
})
配置路由模式:
hash: 使用 URL hash 值来作路由。支持所有浏览器,包括不支持 HTML5 History Api 的浏览器。
history: 依赖 HTML5 History API 和服务器配置。
abstract: 支持所有 JavaScript 运行环境,如 Node.js 服务器端。如果发现没有浏览器的 API,路由会自动强制进入这个模式。
vue-router 默认 hash 模式 —— 使用 URL 的 hash 来模拟一个完整的 URL,于是当 URL 改变时,页面不会重新加载。
如果不想要很丑的 hash,我们可以用路由的 history 模式,这种模式充分利用 history.pushState API 来完成 URL 跳转而无须重新加载页面。
const router = new VueRouter({
mode: 'history',
routes: [...]
})
当你使用 history 模式时,URL 就像正常的 url,例如 http://yoursite.com/user/id
方法一,就是在页面中以
元素的形式进行点击导航。
<div id="app">
<h1>Hello App!h1>
<p>
<router-link to="/foo">Go to Foorouter-link>
<router-link to="/bar">Go to Barrouter-link>
p>
<router-view>router-view>
div>
通过to属性来指定目标地址,默认渲染成带有正确链接的a标签。
当用户点击链接后,内部会立刻把to的值传到router.push(),所以这个值可以是一个字符串或者是描述目标位置的对象。
<router-link to="home">Homerouter-link>
<a href="home">Homea>
可以绑定某些数据:
<router-link v-bind:to="'home'">Home</router-link>
<router-link :to="'home'">Home</router-link>
也可以直接传入路由对象:
<router-link :to="{ path: 'home' }">Homerouter-link>
<router-link :to="{ name: 'user', params: { userId: 123 }}">Userrouter-link>
<router-link :to="{ path: 'register', query: { plan: 'private' }}">Registerrouter-link>
router-link会默认被渲染成a标签,也可以设置tag属性来自定义标签:
<router-link to="/foo" tag="li">foorouter-link>
<li>fooli>
不管指定何种类型的标签,它还是会监听点击,触发导航。
设置repalce属性的话,当点击时,会调用 router.replace() 而不是 router.push(),于是导航后不会留下 history 记录。
<router-link :to="{ path: '/abc'}" replace></router-link>
除了使用
创建 a 标签来定义导航链接,我们还可以借助 router 的实例方法,通过编写代码来实现导航。
router.push(location)
想要导航到不同的 URL,则使用 router.push 方法。这个方法会向 history 栈添加一个新的记录,所以,当用户点击浏览器后退按钮时,则回到之前的 URL。
当你点击
时,这个方法会在内部调用,所以说,点击
等同于调用 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' }})
另外,还有router.replace(location)
方法,和在router-link中添加replace属性一个效果,即不会向history添加新纪录,并且替换掉现在的history记录。
router.go(n)
则是在history记录中向前或后退多少步:
// 在浏览器记录中前进一步,等同于 history.forward()
router.go(1)
// 后退一步记录,等同于 history.back()
router.go(-1)
// 前进 3 步记录
router.go(3)
在创建实例的时候要通过router配置注入路由,从而让整个应用都有路由功能:
import router from './router'
const app = new Vue({
router
}).$mount('#app')
通过在 Vue 根实例的 router 配置传入 router 实例,下面这些属性成员会被注入到每个子组件:
一个路由信息对象表示当前激活的路由的状态信息,包含了当前 URL 解析得到的信息,还有 URL 匹配到的路由记录。
路由信息对象可以从多个地方获取:
路由信息对象的属性:
$route.path:
字符串,对应当前路由的路径,总是解析为绝对路径,如 “/foo/bar”。
$route.params
一个 key/value 对象,包含了 动态片段 和 全匹配片段,如果没有路由参数,就是一个空对象。
$route.query
一个 key/value 对象,表示 URL 查询参数。例如,对于路径 /foo?user=1
,则有 $route.query.user == 1
,如果没有查询参数,则是个空对象。
$route.name
当前路由的名称
代表当前的路由实例。
有以下属性:
router.app
配置了 router 的 Vue 根实例。
router.mode
路由使用的模式
router.currentRoute
当前路由对应的 路由信息对象.
有以下方法: