Vue Router 学习

我们在构建复杂系统的时候,需要构建多页面来完成不同的功能,在使用多个页面的时候,用层级路径来标示页面。vue router 将组件挂载在路由上的方式来模拟传统的多页应用的效果,从而构建复杂的单页应用。所以路由主要完成的是根据当前的路径完成页面的切换。

如何使用

注册路由

首先构建路由和组件之间的对应关系

// 0. 如果使用模块化机制编程,导入Vue和VueRouter,要调用 Vue.use(VueRouter)

// 1. 定义 (路由) 组件。
// 可以从其他文件 import 进来
const Foo = { template: '
foo
' } const Bar = { template: '
bar
' } // 2. 定义路由 // 每个路由应该映射一个组件。 其中"component" 可以是 // 通过 Vue.extend() 创建的组件构造器, // 或者,只是一个组件配置对象。 // 我们晚点再讨论嵌套路由。 const routes = [ {path: "/foo", component: Foo}, {path: "/bar", component: Bar}, //命名路由的方式 { path: '/user/:userId', name: 'user', component: User } ] // 3. 创建 router 实例,然后传 `routes` 配置 // 你还可以传别的配置参数, 不过先这么简单着吧。 const router = new VueRouter({ routes }) // 4. 创建和挂载根实例。 // 记得要通过 router 配置参数注入路由, // 从而让整个应用都有路由功能 const app = new Vue({ router }).$mount('#app')

路由导航和显示对应的内容

利用模拟,进行页面之间的导航。利用来控制当前路由的对应的控件显示的区域。




Hello App!

Go to Foo Go to Bar User

路由的代码操作

this.$route 用于访问当前的路由,比如this.$route.params.username用于访问动态路由里面的参数

router.push

router.push(location, onComplete?, onAbort?)

// 字符串
router.push('home')

// 对象
router.push({ path: 'home' })

// 命名的路由,给定路由名称的情况下,用这种方式导航
router.push({ name: 'user', params: { userId: '123' }})

// 带查询参数,变成 /register?plan=private
router.push({ path: 'register', query: { plan: 'private' }})

注意:如果提供了 path,params 会被忽略,上述例子中的 query 并不属于这种情况。取而代之的是下面例子的做法,你需要提供路由的 name 或手写完整的带有参数的 path

router.replace

跟 router.push 很像,唯一的不同就是,它不会向 history 添加新记录,而是跟它的方法名一样 —— 替换掉当前的 history 记录。

router.go(n)

这个方法的参数是一个整数,意思是在 history 记录中向前或者后退多少步,类似 window.history.go(n)。

// 在浏览器记录中前进一步,等同于 history.forward()
router.go(1)

// 后退一步记录,等同于 history.back()
router.go(-1)

// 前进 3 步记录
router.go(3)

// 如果 history 记录不够用,那就默默地失败呗
router.go(-100)
router.go(100)

路由的种类

路由匹配顺序

由于动态路由匹配存在,一个路径可能匹配多个路由规则,路由匹配顺序按照路由定义的优先级来,谁先定义,谁的优先级就高。

动态路由匹配

主要用于将属于同一类的不同路由映射到同一个组件里面,路由的不同部分会被参数化匹配,如

  routes: [
    // 动态路径参数 以冒号开头
    { path: '/user/:id', component: User }
  ]
匹配的方式
动态路径参数

一个“路径参数”使用冒号 : 标记。当匹配到一个路由时,参数值会被设置到 this.$route.params,可以在每个组件内使用。于是,我们可以更新 User 的模板,输出当前用户的 ID。
在不同的路由之间进行导航的时候,如果对应的是同一个组件,那么组件会被复用,也就是意味着组件的生命周期钩子不会再被调用。所以想要检测路由的变化和页面的重新刷新,可以了用检测路由变化,或者利用导航守卫。

  watch: {
    '$route' (to, from) {
      // 对路由变化作出响应...
    }
  }
const User = {
  template: '...',
  beforeRouteUpdate (to, from, next) {
    // react to route changes...
    // don't forget to call next()
  }
}
匹配所有路由

主要用以客户端 404 错误,为剩余的路由设置一个默认显示。所以一般放在最后。

{
  // 会匹配所有路径
  path: '*'
}
{
  // 会匹配以 `/user-` 开头的任意路径
  path: '/user-*'
}

当使用一个通配符时,$route.params 内会自动添加一个名为 pathMatch 参数。它包含了 URL 通过通配符被匹配的部分:

// 给出一个路由 { path: '/user-*' }
this.$router.push('/user-admin')
this.$route.params.pathMatch // 'admin'
// 给出一个路由 { path: '*' }
this.$router.push('/non-existing')
this.$route.params.pathMatch // '/non-existing'
高级匹配模式

支持以正则表达式的方式来匹配路由,依赖path-to-regexp来实现。

嵌套路由

实际生活中的应用界面,通常由多层嵌套的组件组合而成。同样地,URL 中各段动态路径也按某种结构对应嵌套的各层组件,例如:

/user/foo/profile                     /user/foo/posts
+------------------+                  +-----------------+
| User             |                  | User            |
| +--------------+ |                  | +-------------+ |
| | Profile      | |  +------------>  | | Posts       | |
| |              | |                  | |             | |
| +--------------+ |                  | +-------------+ |
+------------------+                  +-----------------+

借助 vue-router,使用嵌套路由配置,就可以很简单地表达这种关系。也就是说被路由渲染的组件里面还有包含路由渲染路由。这通过子路由的方式来实现

const router = new VueRouter({
  routes: [
    { path: '/user/:id', component: User,
      children: [
        // 当 /user/:id 匹配成功,
        // UserHome 会被渲染在 User 的  中
        { path: '', component: UserHome },

        // ...其他子路由
        {
          // 当 /user/:id/profile 匹配成功,
          // UserProfile 会被渲染在 User 的  中
          path: 'profile',
          component: UserProfile
        },
        {
          // 当 /user/:id/posts 匹配成功
          // UserPosts 会被渲染在 User 的  中
          path: 'posts',
          component: UserPosts
        }
      ]
    }
  ]
})

显示多个路由视图-命名视图

有时候想同时 (同级) 展示多个视图,而不是嵌套展示,例如创建一个布局,有 sidebar (侧导航) 和 main (主内容) 两个视图,这个时候命名视图就派上用场了。你可以在界面中拥有多个单独命名的视图,而不是只有一个单独的出口。如果 router-view 没有设置名字,那么默认为 default。




构建路由的方式也有变化,变成了多组件

const router = new VueRouter({
  routes: [
    {
      path: '/',
      components: {
        default: Foo,
        a: Bar,
        b: Baz
      }
    }
  ]
})

嵌套路由和命名路由组合

我们也有可能使用命名视图创建嵌套视图的复杂布局。这时你也需要命名用到的嵌套 router-view 组件。我们以一个设置面板为例:

/settings/emails                                       /settings/profile
+-----------------------------------+                  +------------------------------+
| UserSettings                      |                  | UserSettings                 |
| +-----+-------------------------+ |                  | +-----+--------------------+ |
| | Nav | UserEmailsSubscriptions | |  +------------>  | | Nav | UserProfile        | |
| |     +-------------------------+ |                  | |     +--------------------+ |
| |     |                         | |                  | |     | UserProfilePreview | |
| +-----+-------------------------+ |                  | +-----+--------------------+ |
+-----------------------------------+                  +------------------------------+

UserSettings 组件的