使用beforeRouteUpdate遇到的坑

最近做的某个项目有个文件预览的需求,该界面左侧是文件的目录树,右侧是预览,预览这部分是子路由,其path/file/preview/:fileId。点击目录树的文件名,右侧预览的fileId发生变化从而刷新预览的内容。因为预览这块还需要展示文件名称等信息,所以包含文件名称和文件id的数据是通过$routeparams传递过来的。
因用户可能在预览界面做刷新操作,为了防止页面刷新丢失详情数据,笔者使用了sessionStorage来保存stringify后的详情数据。

这样,在用户首次进入预览页面时会触发beforeRouteEnter钩子,在此钩子函数里,sessionStorage是否有保存该fileId的详情数据,有则直接使用,没有的话则将to.params中的详情数据保存到sessionStorage中,并将详情数据保存在组件的data里。

当用户点击目录树查看其他文件时,beforeRouteEnter钩子不会触发了,而是触发beforeRouteUpdate钩子函数,其处理逻辑同上。
这样写看着逻辑很清晰明了了,其主要代码如下:

beforeRouteEnter (to, from, next) { // 首次进入此路由会触发该钩子函数
  next(vm => {
    if (!sessionStorage.getItem('scan_' + to.params.fileId)) {
      sessionStorage.setItem('scan_' + to.params.fileId, JSON.stringify(to.params))
    }
    vm.details = JSON.parse(sessionStorage.getItem('scan_' + to.params.fileId))
  })
},
beforeRouteUpdate (to, from, next) { // fileId发生改变时触发此钩子函数
  if (!sessionStorage.getItem('scan_' + to.params.fileId)) {
    sessionStorage.setItem('scan_' + to.params.fileId, JSON.stringify(to.params))
  }
  this.details = JSON.parse(sessionStorage.getItem('scan_' + to.params.fileId))
  next()
},
data () {
  return {
    details: {} // 预览相关的详情数据
  }
}

如果一切顺利的话,笔者也不会如此大费周章来记录这个所谓beforeRouteUpdate遇到的坑了。

当笔者自信满满的点击第一个文件预览时,正常显示!

OK,没问题!

点击第二个文件预览,它不显示文件!

What is the problem?!

唉,遇到bug再正常不过了o(╥﹏╥)o,开始调试吧~

beforeRouteUpdate里打印details的值,发现其正常显示,但devtools里的details却是空的!

这就奇了怪了!

details的值被谁清空了呢?

各种折腾无果后,笔者突然将目光放在了data函数上,这货定义的details的值为{},该不会是它搞的鬼吧!

抱着试试看的心态分别在beforeRouteUpdatedata函数中做了标记,发现data函数竟然后于beforeRouteUpdate执行。

先执行beforeRouteUpdate,再执行data

这也就能解释为什么无法预览文件了。

知道原因那就好解决了,笔者将代码改动如下:

beforeRouteEnter (to, from, next) {
  next(vm => {
    if (!sessionStorage.getItem('scan_' + to.params.fileId)) {
      sessionStorage.setItem('scan_' + to.params.fileId, JSON.stringify(to.params))
    }
    vm.details = JSON.parse(sessionStorage.getItem('scan_' + to.params.fileId))
  })
},
beforeRouteUpdate (to, from, next) {
  if (!sessionStorage.getItem('scan_' + to.params.fileId)) {
    sessionStorage.setItem('scan_' + to.params.fileId, JSON.stringify(to.params))
  }
  next()
},
data () {
  let details = sessionStorage.getItem('scan_' + this.$route.params.fileId)
  if (details) {
    details = JSON.parse(details)
  }
  return {
    details: details || {}
  }
}

这样文件就能够正常预览了!

你可能感兴趣的:(使用beforeRouteUpdate遇到的坑)