关于vue.js:Vue-Router-进阶笔记

6次阅读

共计 4507 个字符,预计需要花费 12 分钟才能阅读完成。

一、导航守卫
残缺的导航解析流程:

  1. 导航被触发
  2. 在失活的组件里调用 beforeRouteLeave
  3. 调用全局的 beforeEach
  4. 在重用的组件里调用 beforeRouteUpdate
  5. 在路由配置里调用 beforeEnter
  6. 解析异步路由组件
  7. 在被激活的组件里调用 beforeRouteEnter
  8. 调用全局的 beforeResolve
  9. 导航被确认
  10. 调用全局的 afterEach
  11. 触发 DOM 更新
  12. 调用 beforeRouteEnter 守卫中传给 next 的回调函数,创立好的组件实例会作为回调函数的参数传入。

参数或查问的扭转并不会触发进入 / 来到的导航守卫。能够通过观察 $route 对象来应答这些变动,或应用 beforeRouteUpdate 的组件内守卫。
1、全局前置守卫
router.beforeEach

const router = new VueRouter({...})
router.beforeEach(to,from,next) => {
  /*to:Route-- 行将要进入的指标路由对象 */
  /*from:Route-- 以后导航正要来到的路由 */
  /*next:function-- 必须要调用该办法来 resolve 这个钩子。执行成果依赖 next 办法的调用参数。*/
  next()  /* 进行管道中的下一个钩子,若全副执行完了,则导航的状态就是 confirmed。*/
  next(false)  /* 中断以后的导航。如果浏览器的 url 扭转了(可能是用户手动或浏览器后退),那么 url 会重置到 from 路由对应的地址。*/
  next('/')  /* 同下 */
  next({path:'/'})  /* 跳转到一个不同的地址。*/
  next(error)  /* 导航被终止,且谬误会传递给 router.onError()注册过的回调。*/}

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

/* BAD */
router.beforeEach((to, from, next) => {if (to.name !== 'Login' && !isAuthenticated) next({name: 'Login'})
  /* 如果用户未能验证身份,则 `next` 会被调用两次 */
  next()})

/* GOOD */
router.beforeEach((to, from, next) => {if (to.name !== 'Login' && !isAuthenticated) next({name: 'Login'})
  else next()})

2、全局解析守卫
router.beforeResolve– 与 router.beforeEachj 相似,区别为:在导航被确认之前,同时在所有组件内守卫和异步路由组件被解析之后,解析守卫就被调用。
3、全局后置钩子
router.afterEach()– 无 next(), 也不会扭转导航自身

router.afterEach(to,from)=>{//...}

路由配置形式:
1、路由独享的守卫 – 间接在路由配置上定义 beforeEnter 守卫

const router = new VueRouter({
  routes: [
    {
      path: '/user',
      component: User,
      beforeEnter: (to,from,next)=>{}}
  ]
})

2、组件内的守卫
能够在路由组件内间接定义以下路由导航守卫
beforeRouteEnter
beforeRouteUpdate
beforeRouteLeave

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`*/
    this.name = to.params.name
    next()},
  beforeRouteLeave(to, from, next) {
    /* 导航来到该组件的对应路由时调用 */
    /* 能够拜访组件实例 `this`*/
    /* 该守卫能够用来禁止用户在还未保留批改前忽然来到,导航能够通过 next(false)勾销 */
    const answer = window.confirm('还没有保留,确定要来到吗')
    if(answer){next()
    }else{next(false)
    }
  }
}

二、路由元信息 -meta

路由登录拦挡

/*1、在须要做登录验证的路由中设置 meta*/
requireAuth 值为 true
const router = new VueRouter({
  routes = [
    {
      path: '/detail',
      name: 'detail',
      component: Detail,
      meta: {requireAuth: true}
    },
    {
      path: '/login',
      name: 'login',
      component: Login
    }
  ]
})

/*2、router.beforeEach()钩子函数,会在进入每个网页之前被调用,可在该钩子函数内做路由拦挡 */
router.beforeEach((to,from,next) => {
  /* 判断将进入的路由是否须要路由拦挡 */
  if(to.matched.some(record => record.meta.requireAuth){
    /*vuex.state 判断 token 是否存在 */
    if(store.state.token){
      /* 已登录 */
      next()}else{
      next({
        path: '/login',
        query: {redirect: to.fullPath}
      })
    }
  } else {next()
  }
})

三、过渡动效
应用 <transition> 标签将 <router-view> 标签包裹能够增加一些过渡成果,会给在这个 router-view 中的路由都加上同一种成果。
若想给不同的路由加不同的成果,能够在路由组件中设置 <transition> 增加成果

const Foo = {
  template: `
    <transition name="slide">
      <div class="foo">...</div>
    </transition>
  `
}

const Bar = {
  template: `
    <transition name="fade">
      <div class="bar">...</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、导航实现之后获取:
在路由组件的 created 钩子函数中调用获取数据的办法

export default{data (){
    return {loading: false}
  },
  created(){
    // 组件创立实现后获取数据,此时 data 曾经被 observed 了
    this.fetchData()},
  methods: {fetchData() {
      this.loading = true
      // 发动数据申请,此时能够通过 $route.params 获取 url 上的数据
      getPost(this.$route.params.id,(res)=>{//...})
    }
  }
}

2、在导航前获取数据
在要跳转的路由组件中的 beforeRouteEnter 守卫中获取数据,当数据获取胜利后只调用 next()办法。

export default {data () {
    return {
      post: null,
      error: null
    }
  },
  beforeRouteEnter (to, from, next) {getPost(to.params.id, (err, post) => {next(vm => vm.setData(err, post))
    })
  },
  // 路由扭转前,组件就曾经渲染完了
  // 逻辑稍稍不同
  beforeRouteUpdate (to, from, next) {
    this.post = null
    getPost(to.params.id, (err, post) => {this.setData(err, post)
      next()})
  },
  methods: {setData (err, post) {if (err) {this.error = err.toString()
      } else {this.post = post}
    }
  }
}

五、滚动行为
当切换到新路由时,页面滚动到顶部或放弃原先的滚动地位,能够在 router 实例中提供一个 scrollBehavior 办法。

const router = new VueRouter({routes: [...],
  scrollBehavior(to,from,savedPosition){
    //return 冀望滚动到的地位
    //return {x: number, y: number}
    // 滚动到顶部
    //return {x:0,y:0}
    
    //savedPosition 在按下后退和后退按钮时可用
    if(savedPosition) {return savedPosition} else {return {x:0,y:0}
    }
  }
})

模仿滚动到锚点

scrollBehavior(to,from,savedPosition){if(to.hash) {
    return {
      selector: to.hash,
      // 设置平滑滚动
      behavior: 'smooth'
    }
  }
}

六、路由懒加载
为进步加载效率,应用懒加载,让路由被拜访时才加载对应组件。需联合 Vue 异步组件和 webpack

//1、将异步组件定义为返回一个 promise 的工厂函数。const Foo = ()=>{
  Promise.resolve({// 组件定义对象})
}
//2、应用 import 引入组件
import('./Foo.vue')  //import 返回一个 promise

// 可联合两者
const Foo = ()=> import('./Foo.vue')
// 路由在实例化时跟一般的一样

正文完
 0