vue-routerj进阶

导航守卫

提供的导航守卫主要用来通过跳转或取消的方式守卫导航。
有多种机会植入路由导航过程中:全局的, 单个路由独享的, 或者组件级的。
记住参数或查询的改变并不会触发进入/离开的导航守卫。你可以通过观察 $route 对象来应对这些变化

1、全局前置守卫
router.beforeEach((to, from, next) => {
  // ...
})
    每个守卫方法接收三个参数:
    to: Route: 即将要进入的目标 路由对象
    from: Route: 当前导航正要离开的路由
    next: Function: 一定要调用该方法来 resolve 这个钩子。

2、全局解析守卫
    router.beforeResolve 注册一个全局守卫。这和 router.beforeEach 类似,区别是在导航被确认之前,同时在所有组件内守卫和异步路由组件被解析之后,解析守卫就被调用。


3、全局后置钩子
    你也可以注册全局后置钩子,然而和守卫不同的是,这些钩子不会接受 next 函数也不会改变导航本身:
    router.afterEach((to, from) => {
        // ...
    })

4、路由独享的守卫
    你可以在路由配置上直接定义 beforeEnter 守卫:
    routes: [
        {
            path: '/foo',
            component: Foo,
            beforeEnter: (to, from, next) => {
            // ...
            }
        }
    ]
    这些守卫与全局前置守卫的方法参数是一样的。 

5、组件内的守卫 
    你可以在路由组件内直接定义以下路由导航守卫:

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

路由元信息

定义路由的时候可以配置 meta 字段:
一个路由匹配到的所有路由记录会暴露为 $route 对象 (还有在导航守卫中的路由对象) 的 $route.matched 数组

    router.beforeEach((to, from, next) => {
    if (to.matched.some(record => record.meta.requiresAuth)) {
        // this route requires auth, check if logged in
        // if not, redirect to login page.
        if (!auth.loggedIn()) {
        next({
            path: '/login',
            query: { redirect: to.fullPath }
        })
        } else {
        next()
        }
    } else {
        next() // 确保一定要调用 next()
    }
})

过度动效

如果你想让每个路由组件有各自的过渡效果,可
以在各路由组件内使用 并设置不同的 name

单个路由的过渡
const Foo = {
  template: `
    <transition name="slide">
      <div class="foo">...</div>
    </transition>
  `
}
基于路由的动态过渡
<!-- 使用动态的 transition name -->
<transition :name="transitionName">
  <router-view></router-view>
</transition>

// 接着在父组件内
// watch $route 决定使用哪种过渡
watch: {
  '$route' (to, from) {
    const toDepth = to.path.split('/').length
    const fromDepth = from.path.split('/').length
    this.transitionName = toDepth < fromDepth ? 'slide-right' : 'slide-left'
  }

数据获取

进入某个路由后,需要从服务器获取数据。 可以通过两种方式来实现:
1、导航完成之后获取:先完成导航,然后在接下来的组件生命周期钩子中获取数据。在数据获取期间显示“加载中”之类的指示。
2、导航完成之前获取:导航完成前,在路由进入的守卫中获取数据,在数据获取成功后执行导航。

    1、导航完成后获取数据
    当你使用这种方式时,我们会马上导航和渲染组件,然后在组件的 created 钩子中获取数据。这让我们有机会在数据获取期间展示一个 loading 状态,还可以在不同视图间展示不同的 loading 状态。

    2、
    我们在导航转入新的路由前获取数据。我们可以在接下来的组件的 beforeRouteEnter 守卫中获取数据,当数据获取成功后只调用 next 方法。    
    export default {
        data () {
            return {
            post: null,
            error: null
            }
        },
        // 在渲染该组件的对应路由被 confirm(确认) 前调用
        beforeRouteEnter (to, from, next) {
            getPost(to.params.id, (err, post) => {
            next(vm => vm.setData(err, post))
            })
        },
    }


滚动行为

// 当切换到新路由时,想要页面滚到顶部,或者是保持原先的滚动位置
// 这个功能只在支持 history.pushState 的浏览器中可用。
scrollBehavior (to, from, savedPosition) {
  if (savedPosition) {
    return savedPosition
  } else {
    return { x: 0, y: 0 }
  }
}
routes:[{}]


路由懒加载

当打包构建应用时,JavaScript 包会变得非常大,影响页面加载。
如果我们能把不同路由对应的组件分割成不同的代码块,然后当路由被访问的时候才加载对应组件,
这样就更加高效了。
const Foo = () => import('./Foo.vue')

const router = new VueRouter({
  routes: [
    { path: '/foo', component: Foo }
  ]
})


posted @ 2021-01-04 15:39  kgwei  阅读(126)  评论(0编辑  收藏  举报