首先注意:php
思路很简章,在路由元信息中设置一个变量:scrollToTop,即标记是否要回到顶部,而咱们的产品页面 productList是要恢复上次滚动高度的,不回到顶部,因此设置为false
当离开路由的时候,仍是判断这个变量是否为false,是则记录滚动的高度到vuex中 (因此咱们这个变量有2个做用,你要维护2个也能够)
而后每当进入路由页面的时候,若是本路由的scrollToTop为false,则从vuex中读取上次记录的高度,并恢复
首先要注意一点,vue单页应用,切换路由时,滚动高度不会变,由于切换路由时只是切换了页面的内容,与滚动高度
当你在某路由页面的时候,滚动了100像素,而后切换了新的路由页面(改变了页面中的内容),只要新的路由页也能够滚动出100像素, 后退时,滚动高度不变, 这能够说是"BUG"
因此下面代码咱们默认把 scrollToTop为true的设置滚动高度为0
我路由中的配置:vue
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中,维护一个变量用于记录web
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中的相关路由事件里vuex
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里面,不然我试出了乱子..
*/复制代码
当进入不一样分类的产品列表页面,或不一样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
})
}
}复制代码
若是更新或更正再补充。api