vue中前進刷新、後退緩存用戶瀏覽數據和瀏覽位置的實踐

vue中,咱們所要實現的一個場景就是:vue

1.搜索頁面==>到搜索結果頁時,搜索結果頁面要從新獲取數據,瀏覽器

2.搜索結果頁面==>點擊進入詳情頁==>從詳情頁返回列表頁時,要保存上次已經加載的數據和自動還原上次的瀏覽位置。緩存

最近在項目中遇到這個問題,思考了幾套方案,老是不太完善。百度搜到的方案也基本都只能知足一些很簡單的需求。對於複雜一些的狀況,仍是有些不完善的地方。如下是我的對於這種場景的一個摸索,也參考了百度。若有更好的方案,歡迎指出。bash

  • 緩存組件,vue2中提供了keep-alive。首先在咱們的app.vue中定義keep-alive:

<keep-alive>      
    <router-view v-if="$route.meta.keepAlive"/>    
</keep-alive>    
<router-view v-if="!$route.meta.keepAlive"/>複製代碼

這裏是根據路由中的meta源信息中的keepAlive字段來判斷當前路由組件是否須要緩存。這裏的meta的keepAlive是咱們自定義的,固然你也能夠叫別的名字。app

下面在router/index.js即咱們的路由文件中,定義meta信息:函數

// list是咱們的搜索結果頁面
{      
    path: '/list',  
    name: 'List',      
    component: resolve => require(['@/pages/list'], resolve),    
    meta: {        
        isUseCache: false,  // 這個字段的意思稍後再說      
        keepAlive: true  // 經過此字段判斷是否須要緩存當前組件  
    }    
},複製代碼

上面的component: resolve => require(['@/pages/list'], resolve)這裏的組件引入方式可能和你們平時寫的有些不同,這裏是爲了路由的懶加載用的,你們能夠忽略。按照正常的import引入也能夠,這個和本次的主題無關。如此一來,vue的路由會幫咱們去緩存list頁面。ui

  • 刷新數據or緩存數據的實現:

說這以前,先簡單說一下和緩存相關的vue鉤子函數。this

設置了keepAlive緩存的組件:spa

       第一次進入:beforeRouterEnter ->created->…->activated->…->deactivatedcode

       後續進入時:beforeRouterEnter ->activated->deactivated

能夠看出,只有第一次進入該組件時,纔會走created鉤子,而須要緩存的組件中activated是每次都會走的鉤子函數。因此,咱們要在這個鉤子裏面去判斷,當前組件是須要使用緩存的數據仍是從新刷新獲取數據。思路有了,下面咱們來實現:

// list組價的activated鉤子
activated() {
    // isUseCache爲false時才從新刷新獲取數據
    // 由於對list使用keep-alive來緩存組件,因此默認是會使用緩存數據的         
    if(!this.$route.meta.isUseCache){            
        this.list = []; // 清空原有數據
        this.onLoad(); // 這是咱們獲取數據的函數
    } 
},複製代碼

這裏的isUseCache 其實就是咱們用來判斷是否須要使用緩存數據的字段,咱們在list的路由的meta中已經默認設置爲false,因此第一次進入list時是獲取數據的。

因爲咱們只要列表到詳情頁的時候緩存列表頁的數據,因此咱們要在列表頁的beforeRouteLeave的鉤子判斷,若是前往的是詳情頁面,則緩存數據:

// 列表頁面的beforeRouteLeave鉤子函數
beforeRouteLeave (to, from, next) {        
    if (to.name == 'Detail') {
        from.meta.isUseCache = true;    
    }        
    next();
},複製代碼

如今,detail返回list頁面。list頁面已經被緩存數據了,那麼如今若是前往search頁面後再前往list頁面時怎麼讓list頁面不使用緩存數據而是獲取新數據呢?答案就在list頁面的activated鉤子中:

// list組價的activated鉤子
 activated() {
    // isUseCache爲false時才從新刷新獲取數據
    // 由於對list使用keep-alive來緩存組件,因此默認是會使用緩存數據的         
    if(!this.$route.meta.isUseCache){            
        this.list = []; // 清空原有數據
        this.onLoad(); // 這是咱們獲取數據的函數   
    }
    // 經過這個控制刷新
    this.$route.meta.isUseCache = false;
},複製代碼

咱們加了一行this.$route.meta.isUseCache=false;也就是從detail返回list後,將list的isUseCache字段爲false,而從detail返回list前,咱們設置了list的isUseCache爲true。因此,只有從detail返回list才使用緩存數據,而其餘頁面進入list是從新刷新數據的。

至此,一個前進刷新、後退返回的功能基本完成了。

若是場景再複雜一丟丟,好比,若是這個詳情頁是個訂單詳情,那麼在訂單詳情頁可能會有刪除訂單的操做。那麼刪除訂單操做後會返回訂單列表頁,是須要列表頁從新刷新的。那麼咱們須要此時在訂單詳情頁進行是否要刷新的判斷。簡單改造一下詳情頁:

data () {    
    return {
        isDel: false  // 是否進行了刪除訂單的操做       
    }
},
beforeRouteLeave (to, from, next) {        
    if (to.name == 'List') {
        // 根據是否刪除了訂單的狀態,進行判斷list是否須要使用緩存數據
        to.meta.isUseCache = !this.isDel;                
    }        
    next();    
},
methods: {        
    deleteOrder () {       
        // 這裏是一些刪除訂單的操做

        // 將狀態變爲已刪除訂單
        // 因此beforeRouteLeave鉤子中就會將list組件路由的isUseCache設置爲false    
        // 因此此時再返回list時,list是會從新刷新數據的 
        this.isDel = true; 
        this.$router.go(-1)
    }
}複製代碼

至此,算是解決了個人vue項目中的這個前進刷新、後退緩存數據和瀏覽位置的問題。

最後再提一下,頁面滾動位置的問題。

問題1:咱們知道,在vue這種單頁應用中,若是你在a頁面滾動了一段距離後,此時前往b頁面後,b頁面也會停留在a頁面的滾動位置。這個問題的解決,咱們能夠利用router自己提供的功能來解決:

routes: [    
    {      
        path: '/detail',      
        name: 'Detail',      
        component: resolve => require(['@/pages/detail'], resolve)    
    }    
],
scrollBehavior (to, from, savedPosition) {
    if (savedPosition) {        
          return savedPosition    
    } else {      
          if (from.meta.keepAlive) {        
               from.meta.savedPosition = document.body.scrollTop;      
          }        
          return { x: 0, y: to.meta.savedPosition || 0 }    
    }  
}複製代碼

scrollBehavior是路由提供的基礎功能,這段函數寫的是:

1.若是經過瀏覽器自帶的前進後退按鈕切換的路由,那麼會自動使用瀏覽默認的回滾上次頁面的瀏覽位置。

2.若是是經過vue路由進行的頁面切換。例如a前往b,首先判斷a是否是經過keep-alive緩存的組件,若是是,則在a路由的meta中添加一個savedPosition字段,而且值爲a的滾動位置。最後return的是頁面須要回滾的位置。如此一來,若是打開一個頁面,該頁面的組件路由中meta.savedPosition爲undefined的話,則頁面滾動到(0,0)的位置,這樣解決了問題1。那麼若是打開一個頁面,它的路由的meta.savedPosition有值的話,則滾動到上次瀏覽的位置,由於meta.savedPosition保存的就是上次瀏覽的位置。


若是以爲有幫助的話,就收藏一下吧!

相關文章
相關標籤/搜索