vue router路由自定義後退事件,並通知下個路由為後退

johnshere發表於2019-03-04

開發過程中發現router和history都不會提供後退事件標識,並且很多時候我們並不想要後退歷史,而是後退頁面層級。

並且在頁面跳轉過程中如果使用go(-1),back()這種事件還容易出現迴圈後退這種場景。如:z->a->b->a;在這樣情況如果在a,b中使用後退,將會按照瀏覽器歷史後退,那麼a/b頁面就會迴圈,而我們在a頁面實際是想要退回到z。
同時vue router還是瀏覽器都沒有地方判斷是否為後退場景,我們很多頁面在使用者體驗上是要區分是否為後退的。

所以為了解決這個問題我在router上面增加了一段邏輯來實現記錄路由軌跡,不同與瀏覽器記錄的歷史我們不需要記錄使用者操作的全部記錄。我們只需要關注使用者操作的路由的先後順序即可。

import Vue from `vue`
import Router from `vue-router`

Vue.use(Router)

let router = new Router({
  routes: [
   ...
  ]
})

// 記錄使用者瀏覽頁面的地址的軌跡
router.routesArr = []
// 後退到上一層頁面,不是上一個歷史
router.backward = function (stepNum) {
  typeof stepNum !== `number` && (stepNum = 1)
  stepNum = Math.abs(stepNum)
  let index = router.routesArr.length - 1 - stepNum
  let route = router.routesArr[0]
  if (index > 0) {
    route = router.routesArr[index]
  }
  router.push({
    name: route.name,
    // path: route.path,
    params: { isBack: true },
    query: route.query
  })
}
// 判斷某一個路由是否在軌跡中出現
router.getIndexOf = path => {
  for (let i in router.routesArr) {
    let route = router.routesArr[i]
    if (route.path === path) {
      return i
    }
  }
  return -1
}
// 記錄使用者瀏覽頁面的地址的軌跡,只保留單一節點
router.afterEach((to, from) => {
  let index = router.getIndexOf(to.path)
  if (index !== -1) {
    router.routesArr.splice(index, 900)
  }
  router.routesArr.push(to)
})

export default router
複製程式碼

記錄軌跡

// 記錄使用者瀏覽頁面的地址的軌跡,只保留單一節點
router.afterEach((to, from) => {
  let index = router.getIndexOf(to.path)
  if (index !== -1) {
    router.routesArr.splice(index, 900)
  }
  router.routesArr.push(to)
})
複製程式碼

我們需要記錄路由的軌跡,並且還得儲存路由的資料,不然後退是引數就會丟失了。這裡使用的全域性後置鉤子函式。注意了,每個路由只保留一次,並且從先後層級上,只留下當前路由及以前的層級。

假使當前軌跡為:z->a->b->c->d,d為當前路由

  1. 後backward()或者go(-1)到c,路由軌跡變為:z->a->b->c
  2. 再push到a,路由軌跡不是變成z->a->b->c->a,而是z->a
  3. 再push到b,路由軌跡變為:z->a->b
    這個記錄是不允許重複的,出現重複則軌跡後退到歷史的某一個點。

前進事件實話說程式碼中使用的不多,這裡就不處理了,用push就行

後退事件並標記

router.backward = function (stepNum) {
  typeof stepNum !== `number` && (stepNum = 1)
  stepNum = Math.abs(stepNum)
  let index = router.routesArr.length - 1 - stepNum
  let route = router.routesArr[0]
  if (index > 0) {
    route = router.routesArr[index]
  }
  router.push({
    name: route.name,
    // path: route.path,
    params: { isBack: true },
    query: route.query
  })
}
複製程式碼

這裡的後退事件不是瀏覽器歷史了,而是路由的先後軌跡
然後找到對應後退的路由資訊,利用push事件將頁面跳轉過去,同時攜帶資料,並傳遞後退標記。

使用

//後退
goback () {
      this.$router.backward()
    }
    
    
    // 判斷是否為後退
if (this.$route.params.isBack) {
  this.transitionEffect = ``
}else {
  this.transitionEffect = `slideInRight`    
}
複製程式碼

相關文章