vue router 进阶 学习笔记

121 阅读3分钟

路由守卫

守卫分为全局守卫,单独路由守卫,组件路由守卫

  • 全局前置守卫
const router = new Router

router.beforeEach((to, from, next => {
    return false
}) 
  • to 即将进入的路由目标

  • from 当前路由

  • return false 则终止当前路由

  • return 一个路由地址 表示当前路由被拦截并导向规定的路由地址

  • next (可选) 只能被调用一次,

  • 全局解析守卫 每次导航都会触发,但是确保导航被确认前 ,组件守卫和异步路由组件被解析后,解析守卫就会被正确使用。

router.beforeResolve(async to => {
    if(to.meta.requireCamera) {
     try {
          await askForCameraPermission()
        } catch (error) {
          if (error instanceof NotAllowedError) {
            // ... 处理错误,然后取消导航
            return false
          } else {
            // 意料之外的错误,取消导航并把错误传给全局处理器
            throw error
          }
        }
    }
})
  • 全局后置钩子 在路由完成之后触发,它能够收集to from信息并作出对应的处理
router.afterEach(())
  • 路由独享守卫 beforeEnter,只在对应的路由进入时候触发,并且当参数改变时不会重复触发
const routes = [
  {
    path: '/users/:id',
    component: UserDetails,
    beforeEnter: (to, from) => {
      // reject the navigation
      return false
    },
  },
]
  • 组件内路由守卫
  • beforeRouteEnter
  • beforeRouteUpdate
  • beforeRouteLeave
const UserDetails = {
  template: `...`,
  beforeRouteEnter(to, from) {
    // 在渲染该组件的对应路由被验证前调用
    // 不能获取组件实例 `this` !
    // 因为当守卫执行时,组件实例还没被创建!
  },
  beforeRouteUpdate(to, from) {
    // 在当前路由改变,但是该组件被复用时调用
    // 举例来说,对于一个带有动态参数的路径 `/users/:id`,在 `/users/1` 和 `/users/2` 之间跳转的时候,
    // 由于会渲染同样的 `UserDetails` 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
    // 因为在这种情况发生的时候,组件已经挂载好了,导航守卫可以访问组件实例 `this`
  },
  beforeRouteLeave(to, from) {
    // 在导航离开渲染该组件的对应路由时调用
    // 与 `beforeRouteUpdate` 一样,它可以访问组件实例 `this`
  },
}

完整的路由解析流程

  1. beforeRouterLeave
  2. beforeEach
  3. beforeRouterUpdate
  4. beforeEnter
  5. 解析异步路由组件
  6. beforeResolve
  7. afterEach

路由元

meta 用于标记并添加额外的路由信息

获取数据

应用场景: user路由下获取用户信息并根据这些信息来渲染页面

  • 在页面的生命周期内获取数据 并提示‘加载中’
  • 在路由导航完成之前,通过路由守卫获取数据,然后将获取的数据传递给导航
// 在路由中获取数据实例
export default {
  data() {
    return {
      post: null,
      error: null,
    }
  },
  beforeRouteEnter(to, from, next) {
    getPost(to.params.id, (err, post) => {
      next(vm => vm.setData(err, post))
    })
  },
  // 路由改变前,组件就已经渲染完了
  // 逻辑稍稍不同
  async beforeRouteUpdate(to, from) {
    this.post = null
    try {
      this.post = await getPost(to.params.id)
    } catch (error) {
      this.error = error.toString()
    }
  },
}

过渡

将组件放在transition 标签中,并根据路由元信息动态设置动画效果

<router-view v-slot="{ Component }">
 <transition :name="route.meta.transition || 'fade'">
    <component :is="Component" />
  </transition>
</router-view>

滚动行为

模拟锚点

const router = createRouter({
  scrollBehavior(to, from, savedPosition) {
    if (to.hash) {
      return {
        el: to.hash,
      }
    }
  },
})

延迟滚动

const router = createRouter({
  scrollBehavior(to, from, savedPosition) {
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve({ left: 0, top: 0 })
      }, 500)
    })
  },
})

动态路由 addRoute removeRoute

查看现有路由

Vue Router 提供了两个功能来查看现有的路由:

  • router.hasRoute:检查路由是否存在。
  • router.getRoutes:获取一个包含所有路由记录的数组。