假设在一个列表中,用户滑动几页点击了详情,此时若再回到列表页,页面状态都已经刷新,用户又需要再进行滑动,这显然是不合理的。
在PC端我们有很多天然优势可以处理这类问题,比如使用分页器让列表不要过长,比如打开详情跳转个新标签页,又或者将详情页面做成抽屉,做成遮罩弹窗等等。。但是在移动端开发中,我们无法避免这个问题,所以有时候就必须记录下页面的状态,让用户在返回时保持页面原有的样子。
在Vue中,我们可以很方便的使用keep-alive
来缓存页面,通常情况下,我们可以通过如下方式改写路由视图:
1 | <keep-alive> |
如上使用了两个if判断,不然会不生效
1 | <!-- 错误写法: --> |
然后我们在需要缓存的页面路由处设置meta即可:
1 | { |
这种就是最常用的方式,在使用了keepAlive之后的页面,生命周期会发生一些变化,比如create和mounted这种页面初始化相关的钩子只会执行一次,因为页面的状态已经不会自动改变了,同时有两个额外的生命周期钩子会生效,分别是:
1 | activated() { |
除此之外使用了keepAlive还有一个副作用,我们会发现页面无法卸载了,也就是销毁的生命周期不再触发了,而且当用户离开列表页,转而又进入列表页的时候,列表页应该是初始化状态而不是缓存状态等情况,这些都使得业务逻辑代码变得繁杂。
为了解决以上的问题,我们采用Vue提供的include
方式来替代if判断
1 | <keep-alive :include="keepPages"> |
并且结合Vuex来管理状态
1 | computed: { |
mutation代码:
1 | changeKeepPages(state, status) { |
然后又写了一份mixin,混入即可将该页面/组件设置为缓存状态:
1 | export default { |
销毁页面可以主动使用:
1 | this.$store.commit('removeKeepPages', 'xxx') // xxx为要销毁的页面名称 |
也可以清空所有缓存的页面,比如在用户回到首页的时候触发:
1 | this.$store.commit('changeKeepPages', 'index') // index这个地方没有实际意义,经测试include为空值时所有页面都会缓存,所以这里才设置了一个不存在的。 |
我这里使用了下面的方式,在回到首页时顺利触发了前一个列表页的销毁事件,这样整个流程就变得十分舒适了,也在一定程度上避免了内存泄漏。