vue单页应用中 返回列表记住上次滚动位置、keep-alive缓存之后更新列表数据 那点事
栏目: JavaScript · 发布时间: 6年前
内容简介:首先注意:思路很简章,在路由元信息中设置一个变量:scrollToTop,即标记是否要回到顶部,而我们的产品页面当离开路由的时候,还是判断这个变量是否为false,是则记录滚动的高度到vuex中 (所以我们这个变量有2个作用,你要维护2个也可以)
实践场景需求
- 产品列表中,滚动到一定位置的时候,点击查看产品信息,后退之后,需要回到原先的滚动位置,这是常见的需求
- 所有页面均在router-view中,暂时使用了keep-alive来缓存所有页面,所以进入不同分类的产品列表,和不同的产品详情页面,需要更新数据
首先注意:
- 本次实践测试环境为pc端的webkit内核浏览器,手机暂时不测试
- 使用$router.back(-1) 和浏览器后退按钮效果一样
- 必须使用keep-alive缓存路由页面才能记住上次的位置,否则使用浏览器后退或$router.back后退都会重新加载数据,使原来的内容高度改变
- 使用keep-alive之后,路由页面才能使用activated事件
记录上次列表滚动的高度位置,后退时恢复
思路很简章,在路由元信息中设置一个变量:scrollToTop,即标记是否要回到顶部,而我们的产品页面 productList 是要恢复上次滚动高度的,不回到顶部,所以设置为false
当离开路由的时候,还是判断这个变量是否为false,是则记录滚动的高度到vuex中 (所以我们这个变量有2个作用,你要维护2个也可以)
然后每当进入路由页面的时候,如果本路由的scrollToTop为false,则从vuex中读取上次记录的高度,并恢复
首先要注意一点,vue单页应用,切换路由时,滚动高度不会变,因为切换路由时只是切换了页面的内容,与滚动高度
当你在某路由页面的时候,滚动了100像素,然后切换了新的路由页面(改变了页面中的内容),只要新的路由页也可以滚动出100像素, 后退时,滚动高度不变, 这可以说是"BUG"
所以下面代码我们默认把 scrollToTop为true的设置滚动高度为0
我路由中的配置:
routes: [{ path: '/', name: 'home', component: Home, meta: { title: "凤凰旅游" ,scrollToTop:true} }, { path: '/product', name: 'product', component: () => import('./views/Product.vue'), meta: { title: "旅游" ,scrollToTop:true} }, { path: '/productList/:id', name: 'productList', component: () => import('./views/productList.vue'), meta: { title: "列表" ,scrollToTop:false} }, { path: '/productShow/:id', name: 'productShow', component: () => import('./views/productShow.vue'), meta: { title: "旅游产品显示" ,scrollToTop:true} } ]复制代码
接下来在store.js中,维护一个变量用于记录
import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex) export default new Vuex.Store({ state: { scrollTop :0 }, mutations: { recordScrollTop(state,n){ state.scrollTop = n } }, actions: { } })复制代码
在main.js中的相关路由事件里
router.beforeEach(function(to,from,next){ document.title = to.meta.title // 要离开页面如果设置为不滚回到顶部,则本页是要记住上滚动高度到vuex中,以便下次进来恢复高度 if(from.meta.scrollToTop==false) { store.commit('recordScrollTop', document.documentElement.scrollTop) } next() }) router.afterEach((to, from) => { // 如果进入后的页面是要滚动到顶部,则设置scrollTop = 0 //否则从vuex中读取上次离开本页面记住的高度,恢复它 if(to.meta.scrollToTop==true){ setTimeout(()=>{ document.documentElement.scrollTop = 0 },10) }else{ setTimeout(()=>{ document.documentElement.scrollTop = store.state.scrollTop },50) } });复制代码
/* * 读取上次记录的滚动高度并且设置,必须放在router.afterEach里面 * 由于缓存了产品列表页面,每次进入会判断如果进入的是否为新的类别,则清空数据再重新加载数据,这时想设置scrollTop就无效,应该是视图渲染更新是异步的原因 * 看官方文档说调用afterEach之后,才触发 DOM 更新 * 所以afterEach里面的有涉及到DOM的操作,放在setTimeout里面,否则我试出了乱子.. */复制代码
使用了keep-alive缓存了页面之后,当参数不同的时候,更新数据
当进入不同分类的产品列表页面,或不同id的产品页面,由于缓存了上次的结果,当然要我们来处理更新
首先上面有说到,使用了keep-alive,路由页面便可以使用activated事件,因为使用了keep-alive其它普通的生命周期只执行了一次,而activated每次显示页面都会激活(类似小程序的onShow),必须使用这个来更新
思路:在页面data中维护一个id,默认为0 ,每次进这个页面时调用activated事件,在事件时面,判断这个id是否与路由url中的参数一致
如果不一致,则根据这个id更新相关数据,并且 把data中的id,更新为新的id ,别忘了还要清空上次分类的产品数据
当然别忘了,你应该初始读取一次数据,比如在created里面, 而activated第一次创建页面时不会激活,缓存之后,第二次进入才会开始激活(我想应该是如此。。)
上代码:
activated(){ //由于缓存了本页面,每次激活页面都要判断是否重置相关参数,并重新加载数据 if(this.id !== this.$route.params.id){this.id = this.$route.params.id //更新分类id this.curpage = 1 //初始化页面为1 this.product = [] //清空上次不同分类的产品数据 this.getProduct('/api/productList.php',this.id,this.curpage).then((res)=>{ this.ptotal = res.total res.products.forEach((item)=>{ this.product.push (item) }) this.loading = false }) } }复制代码
如果更新或更正再补充。
以上所述就是小编给大家介绍的《vue单页应用中 返回列表记住上次滚动位置、keep-alive缓存之后更新列表数据 那点事》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- React通过redux缓存列表数据以及滑动位置,回退时恢复页面状态
- C#列表到列表转换
- Python笔记(二):列表+列表数据处理+函数
- python创建列表和向列表添加元素方法
- 在Bootstrap开发框架中使用bootstrapTable表格插件和jstree树形列表插件时候,对树列表条件和查询...
- Python 列表(List)
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Android 源码设计模式解析与实战
何红辉、关爱民 / 人民邮电出版社 / 2015-11 / 79.00元
本书专门介绍Android源代码的设计模式,共26章,主要讲解面向对象的六大原则、主流的设计模式以及MVC和MVP模式。主要内容为:优化代码的首步、开闭原则、里氏替换原则、依赖倒置原则、接口隔离原则、迪米特原则、单例模式、Builder模式、原型模式、工厂方法模式、抽象工厂模式、策略模式、状态模式、责任链模式、解释器模式、命令模式、观察者模式、备忘录模式、迭代器模式、模板方法模式、访问者模式、中介......一起来看看 《Android 源码设计模式解析与实战》 这本书的介绍吧!