vue中前進刷新、后退緩存,列表緩存和回到原位置


vue中,我們所要實現的一個場景就是:
1.搜索頁面==>到搜索結果列表頁時,搜索結果列表頁面要重新獲取數據,
2.搜索結果列表頁面==>點擊進入詳情頁==>從詳情頁返回列表頁時,要保存上次已經加載的數據和自動還原上次的瀏覽位置。

  • 緩存組件,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是我們自定義的,當然你也可以叫別的名字。

  • 下面在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引入也可以,

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

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

設置了keepAlive緩存的組件:

   第一次進入:beforeRouterEnter ->created->…->activated->…->deactivated 后續進入時: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時是獲取數據的。

當我們從詳情頁返回時,我們把list頁面路由的isUseCache設置成true,這樣我們在返回list頁面時會使用緩存數據:

 // 詳情頁面的beforeRouteLeave鈎子函數 beforeRouteLeave (to, from, next) { if (to.name == 'List') { to.meta.isUseCache = true; } next(); }, 

我們這里是在即將離開detail頁面前判斷是否返回的列表頁。如果是返回list頁面,則把list頁面路由的isUseCache字段設置成true。為什么這樣設置呢?因為我們對list組件使用的keep-alive進行緩存組件,其默認就是使用緩存的。而我們又在list組件的actived鈎子函數中進行了判斷:只有在list頁面的isUseCache==false時才會清空原有數據並重新獲取數據。所以此處設置isUseCache為true,此時返會list頁面是不會重新獲取數據的,而是使用的緩存數據。

detail返回list可以緩存數據了,那么search前往list頁面時怎么讓list頁面不使用緩存數據而是獲取新數據呢?我們重新回到list的activated鈎子中:

 // list組價的activated鈎子 activated() { // isUseCache為false時才重新刷新獲取數據 // 因為對list使用keep-alive來緩存組件,所以默認是會使用緩存數據的 if(!this.$route.meta.isUseCache){ this.list = []; // 清空原有數據 this.onLoad(); // 這是我們獲取數據的函數 } else { this.$route.meta.isUseCache = false; } },

當有篩選條件時建議
  //列表頁面的beforeRouteLeave鈎子函數,去除篩選條件,相對於刷新
  beforeRouteLeave(to, from, next) {
    if (to.name == "declareHome") {  //返回其他頁面,比如上一頁
      location.reload()
    }
    next();
  },

我們加了一行this.$route.meta.isUseCache=false;也就是從detail返回list后,將list的isUseCache字段為false,而從detail返回list前,我們設置了list的isUseCache為true。所以,只有從detail返回list才使用緩存數據,而其他頁面進入list是重新刷新數據的。

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

  • 在一種情況,緩存頁 進入的不是detail頁面,而是去的別的頁面,返回的時候也不讓緩存也刷新,

在進入的頁面中寫鈎子函數:

beforeRouteLeave (to, from, next) { console.log(to.name) console.log(from.name) //打印一下值 哪一個打印的值等於緩存頁面的name 那鈎子if 判斷語句中就寫to.name或者 from.name //條件和判斷語句中一起變動, 要么都是to. 要么都是from. if (to.name == 'List') { to.meta.isUseCache = true; } next(); }, 
這種緩存頁面進入別的頁面,從別的頁面返回緩存頁面,不刷新,其實就是當返回緩存頁面的時候,在activated鈎子函數進入的是else條件語句,而不是進入的刷新頁面語句
不管是列表緩存頁面進入詳情頁,還是進入其他的頁面,返回時位置不變,是要和滾動事件搭配使用 
//1.給窗口添加滾動事件  //親測此條可省略 window.addEventListener("scroll", () => { // console.log(123) var scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop; // console.log(scrollTop) // 獲取到頁面的滾動出的距離,把值存在緩存中, },true); 
等到返回到緩存頁面的時候 可以在activated鈎子函數中的else中 和 this.$route.meta.isUseCache = false寫一起 , 設置滾動出去的距離就等於從localStorage.getItem() 拿出存的距離,這樣就做好了,可以用beforeRouteLeave鈎子函數想讓哪個頁面刷新或者不刷新都可以做到了
activated() { // isUseCache為false時才重新刷新獲取數據 // 因為對list使用keep-alive來緩存組件,所以默認是會使用緩存數據的 if(!this.$route.meta.isUseCache){ this.list = []; // 清空原有數據 this.onLoad(); // 這是我們獲取數據的函數 } else { this.$route.meta.isUseCache = false; } }, 
  • 如果場景再復雜一丟丟,比如,如果這個詳情頁是個訂單詳情,那么在訂單詳情頁可能會有刪除訂單的操作。那么刪除訂單操作后會返回訂單列表頁,是需要列表頁重新刷新的。那么我們需要此時在訂單詳情頁進行是否要刷新的判斷。簡單改造一下詳情頁:

    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項目中的這個前進刷新、后退緩存數據和瀏覽位置的問題。

頁面滾動位置的問題。

問題:我們知道,在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保存的就是上次瀏覽的位置。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM