vue-router

2021-05-08  本文已影响0人  清苑折纸

Vue Router 是 Vue.js (opens new window) 官方的路由管理器。它和 Vue.js 的核心深度集成,让构建单页面应用变得易如反掌。

使用

npm install vue-router

如果在一个模块化工程中使用它,必须要通过 Vue.use() 明确地安装路由功能,然后在HTML文件内使用<router-link>来导航,其中to属性指向指定导航链接,<router-link>会被渲染为一个a标签。使用<router-view>来指明路由出口,即将路由匹配到的组件渲染到该位置。当<router-link>对应的路由匹配成功,将自动设置class属性.router-link-active

import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)
<div id="app">
  <h1>Hello App!</h1>
  <p>
    <router-link to="/foo">Go to Foo</router-link>
    <router-link to="/bar">Go to Bar</router-link>
  </p>
  <router-view></router-view>
</div>
const Foo = { template: '<div>foo</div>' }
const Bar = { template: '<div>bar</div>' }
const routes = [
  { path: '/foo', component: Foo },
  { path: '/bar', component: Bar }
]
// 创建 router 实例,然后传 `routes` 配置
const router = new VueRouter({
  routes // (缩写) 相当于 routes: routes
})
// 4. 创建和挂载根实例。
const app = new Vue({
  router
}).$mount('#app')

我们可以在任何组件内通过 this.$router 访问路由器,也可以通过 this.$route 访问当前路由

动态路由

动态路由参数可以使用 : 标记,比如当我们需要编辑不用id的文章时可以

const User = {
  template: '<div>edit</div>'
}

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

此时/edit/1和/edit/2都指向相同的路由,其中被 : 标记的路径参数可以被this.$route.params获取到

其中当路由参数改变时组件会被复用,并不是被销毁后再重新创建,也就是说组件的生命周期钩子不会再次被调用。

//通配符用来匹配任意路径,含有通配符的路由一般放在最后面
{
  // 会匹配所有路径,通常用于客户端 404 错误
  path: '*'
}
{
  // 会匹配以 `/user-` 开头的任意路径
  path: '/user-*'
}

嵌套路由时在被嵌套的组件内使用router-view来显示组件,路由配置如下:

const router = new VueRouter({
  routes: [
    {
      path: '/user/:id',
      component: User,
      children: [
        {
          path: 'profile',
          component: UserProfile
        },
        {
          path: 'posts',
          component: UserPosts
        }
      ]
    }
  ]
})

路由跳转(path和params同时使用params不生效)

router.push(location, onComplete?, onAbort?)
想要导航到不同的 URL,则使用 router.push 方法。这个方法会向 history 栈添加一个新的记录,所以,当用户点击浏览器后退按钮时,则回到之前的 URL。

const userId = '123'
router.push({ name: 'user', params: { userId }}) // -> /user/123
router.push({ path: `/user/${userId}` }) // -> /user/123
// 这里的 params 不生效
router.push({ path: '/user', params: { userId }}) // -> /user

如果跳转到相同的动态路由地址则需要调用beforeRouteUpdate来响应这个变化,因为此时属于组件被复用,生命周期钩子不会被调用
router.replace(location, onComplete?, onAbort?)
不会向 history 添加新记录,而是跟它的方法名一样 —— 替换掉当前的 history 记录。与<router-link :to="..." replace>作用相同

router.go(n)
this.$router.go(-1) //返回上一级
这个方法的参数是一个整数,意思是在 history 记录中向前或者后退多少步,类似 window.history.go(n)。

一个路由需要使用多个组件时,需要使用命名router-view

<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>

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

路由重定向

const router = new VueRouter({
  routes: [
    { path: '/a', redirect: '/b' }
  ]
})

重定向的目标还可以是一个命名路由,也可以是一个返回路由的方法。

const router = new VueRouter({
  routes: [
    { path: '/a', redirect: to => {
      // return 重定向的 字符串路径/路径对象
    }}
  ]
})

路由组件传参

使用props将组件与路由解耦

const router = new VueRouter({
  routes: [
    {
      path: '/search',
      component: SearchUser,
      props: route => ({ query: route.query.q })
    }
  ]
})

此时会将query:"vue"作为属性传递给 SearchUser 组件,query会附加在域名后。

HTML5 History模式

vue-router默认使用hash模式,此外我们还可以使用history模式

const router = new VueRouter({
 mode: 'history',
 routes: [...]
})

导航守卫

vue-router 提供的导航守卫主要用来通过跳转或取消的方式守卫导航。有多种机会植入路由导航过程中:全局的, 单个路由独享的, 或者组件级的。
参数或查询的改变并不会触发进入/离开的导航守卫。

全局前置守卫

可以通过router.beforeEach来注册

const router = new VueRouter({ ... })
router.beforeEach((to, from, next) => {
  // ...
})

当一个导航触发时,守卫是异步解析执行的,此时导航在所有守卫 resolve 完之前一直处于 等待中。

确保 next 函数在任何给定的导航守卫中都被严格调用一次。它可以出现多于一次,但是只能在所有的逻辑路径都不重叠的情况下,否则钩子永远都不会被解析或报错

全局解析守卫

通过router.beforeResolve注册,与router.beforeEach的区别是在导航被确认之前,同时在所有组件内守卫和异步路由组件被解析之后,解析守卫被调用。

全局后置钩子

通过router.afterEach注册,这些钩子不会接受 next 函数也不会改变导航本身

router.afterEach((to, from) => {
  // ...
})
路由独享守卫

在路由配置上直接定义,例如以下为beforeEnter守卫:

const router = new VueRouter({
  routes: [
    {
      path: '/foo',
      component: Foo,
      beforeEnter: (to, from, next) => {
        // ...
      }
    }
  ]
})
组件内守卫
const Foo = {
  template: `...`,
  beforeRouteEnter(to, from, next) {
    // 在渲染该组件的对应路由被 confirm 前调用
    // 不!能!获取组件实例 `this`,但可以通过传一个回调给 next来访问组件实例。next((vm)=>{...})
    // 因为当守卫执行前,组件实例还没被创建
  },
  beforeRouteUpdate(to, from, next) {
    // 在当前路由改变,但是该组件被复用时调用
    // 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,
    // 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
    // 可以访问组件实例 `this`
  },
  beforeRouteLeave(to, from, next) {
    // 导航离开该组件的对应路由时调用
    // 可以访问组件实例 `this`
  }
}
完整的导航解析流程

定义路由的时候可以配置meta字段,可以通过遍历 $route.matched 来检查路由记录中的 meta 字段。

上一篇 下一篇

猜你喜欢

热点阅读