首先注意: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