[TOC] ***** Vue Router 是[Vue.js](http://cn.vuejs.org/)官方的路由管理器。它和 Vue.js 的核心深度集成,让构建单页面应用变得易如反掌。 **包含的功能有:** * 嵌套的路由/视图表 * 模块化的、基于组件的路由配置 * 路由参数、查询、通配符 * 基于 Vue.js 过渡系统的视图过渡效果 * 细粒度的导航控制 * 带有自动激活的 CSS class 的链接 * HTML5 历史模式或 hash 模式,在 IE9 中自动降级 * 自定义的滚动条行为 ***** # :-: 安装 ## 直接下载 / CDN ``` https://unpkg.com/vue-router/dist/vue-router.js ``` ``` <script src="/path/to/vue.js"></script> <script src="/path/to/vue-router.js"></script> ``` ## NPM ``` npm install vue-router ``` 如果在一个模块化工程中使用它,必须要通过`Vue.use()`明确地安装路由功能: ``` import Vue from 'vue' import VueRouter from 'vue-router' Vue.use(VueRouter) ``` 如果使用全局的 script 标签,则无须如此 (手动安装)。 # :-: 编程式的导航 | 声明式 | 编程式 | | --- | --- | | `<router-link :to="...">` | `router.push(...)` | | `<router-link :to="..." replace>` | `router.replace(...)` | ~~~ const userId = '123' router.push({ name: 'user', params: { userId }}) // -> /user/123 router.push({ path: `/user/${userId}` }) // -> /user/123 ~~~ ~~~ // 带查询参数,变成 /register?plan=private router.push({ path: 'register', query: { plan: 'private' }}) ~~~ Vue Router 的导航方法 (`push`、`replace`、`go`) 在各类路由模式 (`history`、`hash`和`abstract`) 下表现一致。 # :-: 命名视图 有时候想同时 (同级) 展示多个视图,而不是嵌套展示,例如创建一个布局,有`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`配置 (带上 s): ~~~ const router = new VueRouter({ routes: [ { path: '/', components: { default: Foo, a: Bar, b: Baz } } ] }) ~~~ # :-: 重定向 重定向也是通过`routes`配置来完成,下面例子是从`/a`重定向到`/b`: ~~~ const router = new VueRouter({ routes: [ { path: '/a', redirect: '/b' } ] }) ~~~ 重定向的目标也可以是一个命名的路由: ~~~ const router = new VueRouter({ routes: [ { path: '/a', redirect: { name: 'foo' }} ] }) ~~~ 甚至是一个方法,动态返回重定向目标: ~~~ const router = new VueRouter({ routes: [ { path: '/a', redirect: to => { // 方法接收 目标路由 作为参数 // return 重定向的 字符串路径/路径对象 }} ] }) ~~~ 注意[导航守卫](https://router.vuejs.org/zh/guide/advanced/navigation-guards.html)并没有应用在跳转路由上,而仅仅应用在其目标上。在下面这个例子中,为`/a`路由添加一个`beforeEach`或`beforeLeave`守卫并不会有任何效果。 # :-: 别名 “重定向”的意思是,当用户访问`/a`时,URL 将会被替换成`/b`,然后匹配路由为`/b`,那么“别名”又是什么呢? **`/a`的别名是`/b`,意味着,当用户访问`/b`时,URL 会保持为`/b`,但是路由匹配则为`/a`,就像用户访问`/a`一样。** 上面对应的路由配置为: ~~~ const router = new VueRouter({ routes: [ { path: '/a', component: A, alias: '/b' } ] }) ~~~ “别名”的功能让你可以自由地将 UI 结构映射到任意的 URL,而不是受限于配置的嵌套路由结构。 # :-: 路由组件传参 在组件中使用`$route`会使之与其对应路由形成高度耦合,从而使组件只能在某些特定的 URL 上使用,限制了其灵活性。 **通过`props`解耦** ~~~ const User = { props: ['id'], template: '<div>User {{ id }}</div>' } const router = new VueRouter({ routes: [ { path: '/user/:id', component: User, props: true }, // 对于包含命名视图的路由,你必须分别为每个命名视图添加 `props` 选项: { path: '/user/:id', components: { default: User, sidebar: Sidebar }, props: { default: true, sidebar: false } } ] }) ~~~ **这样你便可以在任何地方使用该组件,使得该组件更易于重用和测试。** ## :-: 布尔模式 如果`props`被设置为`true`,`route.params`将会被设置为组件属性。 ## :-: 对象模式 如果`props`是一个对象,它会被按原样设置为组件属性。当`props`是静态的时候有用。 ~~~ const router = new VueRouter({ routes: [ { path: '/promotion/from-newsletter', component: Promotion, props: { newsletterPopup: false } } ] }) ~~~ ## :-: 函数模式 你可以创建一个函数返回`props`。这样你便可以将参数转换成另一种类型,将静态值与基于路由的值结合等等。 ~~~ const router = new VueRouter({ routes: [ { path: '/search', component: SearchUser, props: (route) => ({ query: route.query.q }) } ] }) ~~~ URL`/search?q=vue`会将`{query: 'vue'}`作为属性传递给`SearchUser`组件。 请尽可能保持`props`函数为无状态的,因为它只会在路由发生变化时起作用。如果你需要状态来定义`props`,请使用包装组件,这样 Vue 才可以对状态变化做出反应。