甲爸爸提了一个需求, 希望公众号内的商城能够像 App 一样, 从商品详情页跳转至列表页及其他列表页时, 可以实现列表页缓存(数据不刷新, 位置固定到之前点的商品的位置)
本来想着 scrollBehavior 应该可以满足, 但是实际操作中发现: 如果列表带着分页, 位置是不会定位到点击的位置的
在网上转了一圈, 终于找到适合自己的方法 --beforeRouteLeave
注: beforeRouteLeave 只对一级页面起作用, 不适用于 children 中的其他二级或其他级别的页面
以上是准备工作, 接下来 可以步入正题了:
找到入口挂载页面: App.vue 在 router-view 外部包裹一个 keep-alive 的标签
因为不是所有页面都需要缓存, 所以把需要缓存的页面中加入 name 值, 并将 name 值加入 keep-alive 中
- <keep-alive v-if="isRouterAlive" include="starShop">
- <router-view></router-view>
- </keep-alive>
当然, 仅仅是这些, 是不能实现缓存的,
刚开始我是学着网上的方法, 这样写的, 当从列表点入详情页时, 就将列表页的 keepalive 值, 赋为 true(实现缓存)
- beforeRouteLeave(to, from, next) {
- if(from.path == '/sale/newGoods/index' && to.path == '/goods/detail') {
- from.meta.keepAlive = true;
- this.loading = true;
- next();
- return
- } else {
- from.meta.keepAlive = false;
- Windows.location.reload();
- this.$destroy();
- next();
- return
- }
- },
但是后期甲爸爸发现一个 bug: 当我从列表一点击进入详情之后, 如果直接从详情页, 点击进入别的店铺列表页, 即列表二, 最新的列表页内展示的商品列表是之前的数据, 并没有变为最新的店铺列表内容, 即列表二页面展示的还是列表一的商品
玩大了, 这个问题比较着急啊, 万一把顾客绕晕了, 人家不买东西了, 那我罪过不就大了咩
晚上趁着月黑风高, 夜深人静的时候, 我苦思冥想, 终于把这个社会毒瘤挖掉了
我绝不是屈居于甲爸爸的淫威之下, 只是因为我对技术的执著, 过度追求完美的我, 忍受不聊我的东西出现这样大的漏洞
要看解决办法的直接来这 ↓↓↓↓↓↓
首先摒弃上面的列表页面的方法
第一步: 找到商品详情页, 最为主角之一, 我在这里用到了 beforeRouteEnter,beforeRouteLeave
- beforeRouteEnter (to, from, next) {
- next(vm =>{
- vm.formUrl = from.path;
- console.log(vm.formUrl)
- });
- },
- beforeRouteLeave(to, from, next) {
- to.meta.keepAlive = false;
- if(to.path == this.formUrl){
- to.meta.keepAlive = true;
- next();
- return
- }else{
- to.meta.KeepAlive = false;
- Windows.localStorage.removeItem('isRefresh')
- this.$destroy();
- next();
- return
- }
- },
beforeRouteEnter: 进入路由之前执行的函数(拿到列表一的路由)
beforeRouteLeave: 离开路由之前执行的函数(拿到列表二的路由)
通过这两个钩子, 可以成功的拿到事件的另外两位主角路由(列表一, 列表二)
在详情页中, 当离开该页之前, 在 beforeRouteLeave 内进行列表一, 列表二的路由比较
若两路由相同, 则跳转目的页面 (to.meta.keepAlive) 值为 true, 列表页面进行缓存(比如从详情页返回的时候)
若两路由不同, 则跳转目的页面发生了变化 (比如从鞋帽列表 --> 鞋子商品 -->鞋子列表), 则鞋子列表页面不需要缓存, 需要刷新获取最新的鞋子列表数据
第二步: 处理事件的第二主角 -- 列表页面
这里我仅用到了 beforeRouteEnter
这个钩子中, 我们可以拿到当前页面的 keepAlive 值
这个值是在详情页中就已经给定的
如果是 true, 表示缓存, 否则为不缓存(刷新)
防止页面一直刷新, 变成死亡函数, 我们要在 data 中声明一个变量 isRefresh
- isRefresh: Windows.localStorage.getItem('isRefresh') || true
- beforeRouteEnter (to, from, next) {
- next(vm =>{
- if(to.meta.keepAlive != true && to.meta.keepAlive != null){
- vm.goods=[];
- Windows.localStorage.setItem('isRefresh',true)
- if(JSON.stringify(Windows.localStorage.getItem('isRefresh')) != false){
- Windows.localStorage.setItem('isRefresh',false)
- location.reload();
- }
- }
- });
- return
- },
如果当前页 to.meta.keepAlive 值不为 true, 且值存在, 则需刷新页面
防止页面一直刷新,
Windows.localStorage.setItem('isRefresh',true)
设置缓存变量 isRefresh, 值为 true(表示需要刷新)
当 to.meta.keepAlive 值不为 true 且 isRefresh 值为 true, 页面刷新, 且 isRefresh 赋值为 false, 即关闭刷新
vm.goods=[]; 是当页面跳去新的列表页刷新之前, 会出现短暂的列表展示, 为了避免不必要的误导, 在检测到是跳转到新的列表页时, 我将列表页的 goods 列表情况, 视觉感受会好一些
因项目不同而异, 不需要可以去掉
多张页面之间跳转, 判断是否需要缓存或刷新获取新数据, 就是这样了
或许因为业务需求不同, 技术处理方式可能会不同, 希望能帮助到各位, 或者给各位一些启发
来源: https://www.cnblogs.com/tongjiaojiao/p/10606153.html