vue使用keep-alive保持滾動條位置的實現


簡單介紹,使用keep-alive的時候,返回前一頁,沒有保持滾動條位置。
事實上,就算不使用keep-alive,位置也沒有被記錄。
但是,在不使用keep-alive的時候,頁面內容會刷新,所以就隨他去了……就是這么任性……

 

思路

官方有推薦一個scrollBehavior,鏈接,但是上面標注,只在history.pushState的瀏覽器生效,不知道是不是只能開啟history.pushState才可以使用,看了下實現,挺不友好的,還是自己搞一個吧。。。

實現思路是這樣的,首先給路由增加一個對象meta:

meta: { keepAlive: true, scrollTop: 0, }

keepAlive是否需要保持頁面,scrollTop記錄頁面的滾動位置。
然后在app.vue增加如下入口:

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

這樣就啟用keep-alive了。
然后在全局main.ts增加一個全局路由控制:

router.beforeEach((to: Route, from: Route, next: () => void) => { if (from.meta.keepAlive) { const $content = document.querySelector('#content'); const scrollTop = $content ? $content.scrollTop : 0; from.meta.scrollTop = scrollTop; } next(); });

很簡單,離開的時候判斷當前頁是否需要保持頁面,如果需要,記錄頁面主容器content的滾動位置,寫入路由。
然后,每次進入保持好的頁面,讀取滾動條位置scrollTop,修改主容器的scrollTop,就搞定了:

public activated() { const scrollTop = this.$route.meta.scrollTop; const $content = document.querySelector('#content'); if (scrollTop && $content) { $content.scrollTop = scrollTop; } }

看起來很簡單哦。

 

遺留問題

1、是不是每個頁面都可以記錄滾動條位置呢?

其實不是的,有的頁面,內部有js交互,比如tab交互,不同的tab,頁面可滾動的高度不一致,如果不保持頁面狀態而統一記錄滾動位置,有可能導致滾動條的位置錯位。  

2、能不能把activated這一步寫到全局的main.ts或者state去呢?

有想過這點,但是目前來說,沒找到實現的方法。 首先,如果通過router來控制,做不到,全局路由控制只能在頁面加載前監聽,取不到載入頁的元素。 如果寫在一個通用的全局函數去控制,比如定義一個state,當頁面加載完的時候設置,那需要定義一個mixins來處理,但是對這個mixins不太熟悉,暫時還不知道該怎么做,可能有時間找個方法搞定它。  

沒有啦……

 

后記

今天抽時間看了下官方的scrollBehavior,其實還是很簡單的,但是我用不上,,,
原因是官方使用的滾動條,針對的是元素是#app,但是很遺憾,我的頁面布局決定了,我的滾動條應該給#content元素。

<div id="app"> <div class="wrap"> <div id="header"> <div id="content"> <div id="footer"> ...

所以scrollBehavior只能否決了。
回到mixins,今天也嘗試了一下,但是VSC提示我,在mixin中的activated方法找不到this.$route這個屬性:

類型“vueConstructor<Vue> | ComponentOptions<Vue, DefaultData<Vue>, DefaultMethods<Vue>, DefaultComputed, PropsDefinition<Record<string, any>>, Record<string, any>>”上不存在屬性“$route”。
  類型“VueConstructor<Vue>”上不存在屬性“$route”。

當然,就算提示找不到$route,實際上還是找到了的。
但是這里又有一個問題,mixin會在當前頁每一個組件中都執行一次,在N個組件中會對滾動條操作N次,感覺有點冗贅,不太喜歡。
暫時找不到更好的實現方式了,只能在需要記錄的頁面單獨實現activated...

廣州品牌設計公司https://www.houdianzi.com PPT模板下載大全https://redbox.wode007.com

搞定

下班前,總算搞定了。不廢話,上代碼:
自定義一個mixins:

//mixin.ts import Vue from 'vue'; import Component from 'vue-class-component'; @Component export default class MyMixin extends Vue { public activated() { const scrollTop = this.$route.meta.scrollTop; const $content = document.querySelector('#content'); if (scrollTop && $content) { $content.scrollTop = scrollTop; } } }

在需要記錄scrollTop的頁面引入這個mixins:

// home.vue import { Component, Mixins } from 'vue-property-decorator'; import MyMixin from '@/global/mixin'; @Component export default class Home extends Mixins(MyMixin) { // todo ... }

關鍵在於Mixins,在沒有使用Mixins之前,我們引入的是Vue,組件繼承的也是Vue,現在引入Mixins,組件直接繼承Mixins,然后把我們自定義的mixins傳遞進去,就可以在本頁掛載自定義的Mixins了。
這么處理,基本完成了記錄滾動條的功能,OK~


免責聲明!

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



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