美文网首页
vue-router

vue-router

作者: 清苑折纸 | 来源:发表于2021-05-08 00:00 被阅读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 完之前一直处于 等待中。

    • to: Route: 即将要进入的目标 路由对象
    • from: Route: 当前导航正要离开的路由
    • next: Function: 一定要调用该方法来 resolve 这个钩子。执行效果依赖 next 方法的调用参数。
    • next(): 进行管道中的下一个钩子。如果全部钩子执行完了,则导航的状态就是 confirmed (确认的)。
      中断当前的导航:next(false)
      跳转到一个不同的地址:next('/') 或者 next({ path: '/' })

    确保 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) => {
            // ...
          }
        }
      ]
    })
    
    组件内守卫
    • beforeRouteEnter( 是支持给 next 传递回调的唯一守卫)
    • beforeRouteUpdate
    • beforeRouteLeave
    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`
      }
    }
    
    完整的导航解析流程
    • 导航被触发。
    • 在失活的组件里调用 beforeRouteLeave 守卫。
    • 调用全局的 beforeEach 守卫。
    • 在重用的组件里调用 beforeRouteUpdate 守卫 。
    • 在路由配置里调用 beforeEnter。
    • 解析异步路由组件。
    • 在被激活的组件里调用 beforeRouteEnter。
    • 调用全局的 beforeResolve 守卫 。
    • 导航被确认。
    • 调用全局的 afterEach 钩子。
    • 触发 DOM 更新。
    • 调用 beforeRouteEnter 守卫中传给 next 的回调函数,创建好的组件实例会作为回调函数的参数传入。

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

    相关文章

      网友评论

          本文标题:vue-router

          本文链接:https://www.haomeiwen.com/subject/ysyydltx.html