如何监听vue-router的beforeEach

如何监听vue-router的beforeEach

背景

最近在做一些关于前端监控相关的内容,考虑到能够在团队中快速推广,所以决定有限从无侵入的角度切入。

在处理到屏幕首屏性能时遇到了需要监听路由变化的问题,过程还好,没那么难受

  • 首先确定了单页应用无刷新首屏性能监听方案(这里不展开讲,注意下“无刷新”,刷新的情况可以直接用performance)

  • 其次在全局监听路由变化(单页主要是pushState和replaceState,其次还有go、back等等,不展开讲,感兴趣留言谈论),但是这样的监听不够细致,因为监听到pushState调用前,新页面依赖的JS、CSS资源就已经开始加载了,对监测数据的准确性影响比较大

  • 在研究过程中发现从 vue-router 的beforeEach到pushState结束这个过程中取到的数据还是相对准确的,但是vue-router并没有提供beforeEach的探针,去网上找了下也没有相关的内容,无奈只好自己整理了,闲话不多说,上代码

思路

// main.js - 通常Vue多数依赖都在这里填充
import router from './router' // 引入vueRouter实例

/* 核心代码开始 */
const oldBeforeEach = router.beforeEach
router.beforeEach = function (callBack) {
  const fn = function (...list) {
    console.log('这里可以监听到beforeEach')
    callBack.apply(router, list)
  }
  oldBeforeEach.call(router, fn)
}

/* 核心代码结束 */

const app = new Vue({
  router,
  render: h => h(App)
}).$mount('#app')

思考一下,这里的console.log(‘这里可以监听到beforeEach’)可能会有什么问题

基础代码拆解

  • router.beforeEach = function (callBack) {...}
// vue-router代码
router.beforeEach(fn)

我们知道router.beforeEach是一个函数,接收一个函数为参数,故重写时参数设为callBack

  • callBack的调用为什么要放在另一个函数中
const fn = function (...list) {
  console.log('这里可以监听到beforeEach')
  callBack.apply(router, list)
}
oldBeforeEach.call(router, fn)

由于router.beforeEach只是将函数注册,将其插入一个队列中在适当的时机执行,所以我们想要监听路由变化只能将代码放到传入的方法中,这里依靠一个中间方法来做(如果不考虑兼容性,用Proxy来做更方便一点

  • fn接收参数,callBack使用

这里是因为router.beforeEach处理回调函数时会传入 from、to、next,故需要将其转给callBack

  • 绑定this为router(内部依赖,不过多解释)

总结

到了这里基本就结束了,还记得一开始的思考问题吗,fn 函数中 的 console 问题,前面应该有提到router.beforeEach是一个注册的过程,如果多次调用,会将回调函数放到队列中,在合适的时机执行。

router.beforeEach(() => { console.log(2) })
router.beforeEach(() => { console.log(1) })

// 如果客户端注册过两个回调,fn的console就会被执行两次

好了就到这里了,聪明的你一定知道怎么解决这个小问题,欢迎留言讨论吧

你可能感兴趣的:(JS基础)