最近做的某个项目有个文件预览的需求,该界面左侧是文件的目录树,右侧是预览,预览这部分是子路由,其path
为/file/preview/:fileId
。点击目录树的文件名,右侧预览的fileId
发生变化从而刷新预览的内容。因为预览这块还需要展示文件名称等信息,所以包含文件名称和文件id的数据是通过$route
的params
传递过来的。
因用户可能在预览界面做刷新操作,为了防止页面刷新丢失详情数据,笔者使用了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
的值为{}
,该不会是它搞的鬼吧!
抱着试试看的心态分别在beforeRouteUpdate
和data
函数中做了标记,发现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 || {}
}
}
这样文件就能够正常预览了!