美文网首页
Vue-Router进阶

Vue-Router进阶

作者: A郑家庆 | 来源:发表于2019-05-03 22:49 被阅读0次

    路由元信息

    定义路由的时候可以配置meta字段:

    const router = new VueRouter({
      routes: [
        {
          path: '/foo',
          component: Foo,
          children: [
            {
              path: 'bar',
              component: Bar,
              // a meta field
              meta: { requiresAuth: true }
            }
          ]
        }
      ]
    })
    

    那么如何访问这个meta字段呢?
    首先,我们称呼routes配置中的每个路由对象为路由记录。路由记录可以是嵌套的,因此,当一个路由匹配成功后,他可能匹配多个路由记录。
    例如,根据上面的路由配置,/foo/bar这个URL将会匹配父路由记录以及子路由记录。
    一个路由匹配到的所有路由记录会暴露为route对象(还有在导航守卫中的路由对象)的route.matched数组。因此,我们需要遍历$route.matched来检查路由记录中的meta字段。
    下面例子展示在全局导航守卫中检查元字段:

    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()
      }
    })
    

    路由元信息,主要针对路由跳转时对匹配到的路由执行一些操作。

    过渡动效

    <router-view>是基本的动态组件,所以我们可以用<transition>组件给它添加一些过渡效果:

    <transition>
        <router-view></router-view>
    </transition>
    
    单个路由的过渡

    上面的用法会给所有路由设置一样的过渡效果,如果你想让每个路由组件有各自的过渡效果,可以在各路由组件内使用<transition>并设置不同的name。

    <transition name="fade">
        <user-agent></user-agent>
    </transition>
    
    基于路由的动态过渡

    还可以基于当前路由与目标路由的变化关系,动态设置过渡效果:

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

    滚动行为

    使用前端路由,当切换到新路由时,想要页面滚动到顶部,或者是保持原先的滚动位置,就像重新加载页面那样。vue-router能做好,而且更好,它让你可以自定义路由切换时页面如何滚动。
    注意:这个功能只在支持history.pushState的浏览器中可用。
    当创建一个Router实例,你可以提供一个scrollBehavior方法:

    const router = new VueRouter({
      routes: [...],
      scrollBehavior (to, from, savedPosition) {
        // return 期望滚动到哪个的位置
      }
    })
    

    scrollBehavior方法接收to和from路由对象。第三个参数savedPosition当且仅当popstate导航(通过浏览器的前进/后退按钮触发)时才可用。
    这个方法返回滚动位置的对象信息,例如:

    • { x: number, y: number }
    • { selector: string, offset ? : { x: number, y: number } }
      如果返回一个falsy的值或者是一个空对象,那么不会发生滚动。
      举例:
    scrollBehavior (to, from, savedPosition) {
      return { x: 0, y: 0 }
    }
    

    对于所有路由导航,简单地让页面滚动到顶部。
    返回savedPosition,在按下后退/前进按钮时,就会像浏览器的原生表现那样:

    scrollBehavior (to, from, savedPosition) {
      if (savedPosition) {
        return savedPosition
      } else {
        return { x: 0, y: 0 }
      }
    }
    

    如果你要模拟"滚动到锚点"的行为:

    scrollBehavior (to, from, savedPosition) {
      if (to.hash) {
        return {
          selector: to.hash
        }
      }
    }
    
    异步滚动

    你可以返回一个Promise来得出预期的位置描述:

    scrollBehavior (to, from, savedPosition) {
      return new Promise((resolve, reject) => {
        setTimeout(() => {
          resolve({ x: 0, y: 0 })
        }, 500)
      })
    }
    

    将其挂载到从页面级别的过渡组件的事件上,令其滚动行为和页面过渡一起良好运行是可能的。但是考虑到用例的多样性和复杂性,我们仅提供这个原始的接口,以支持不同用户场景的具体实现。

    路由懒加载

    当打包构建应用时,JavaScript包会变得非常大,影响页面加载。如果我们能把不同路由对应的组件分割成不同的代码块,然后当路由被访问的时候才加载对应组件,这样就更加高效了。
    首先,可以将异步组件定义为返回一个Promise的工厂函数(该函数返回的Promise应该resolve组件本身):

    const Foo = () => Promise.resolve({/*组件定义对象*/})
    

    第二,在Webpack2中,我们可以使用动态import语法定义代码分块点:

    import('../Foo.vue')    // 这个 `import` 函数会返回一个 `Promise` 对象。
    

    结合这两者,这就是如何定义一个能够被Webpack自动代码分割的异步组件。

    const Foo = () => import ('../Foo.vue')
    

    在路由配置中什么都不需要改变,只需要像往常一样使用Foo:

    const router = new VueRouter({
      routes: [
        { path: '/foo', component: Foo }
      ]
    })
    
    把组件按组分块

    有时候我们想把某个路由下的所有组件都打包在同个异步块(chunk)中。只需要使用命名chunk,一个特殊的注释语法来提供chunk name。

    const Foo = () => import(/* webpackChunkName: "group-foo" */ './Foo.vue')
    const Bar = () => import(/* webpackChunkName: "group-foo" */ './Bar.vue')
    const Baz = () => import(/* webpackChunkName: "group-foo" */ './Baz.vue')
    

    Webpack 会将任何一个异步模块与相同的块名称组合到相同的异步块中。

    参考文章:https://segmentfault.com/a/1190000015904599

    相关文章

      网友评论

          本文标题:Vue-Router进阶

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