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

前言

下班前,20分鐘,發一篇。。。
簡單介紹,使用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不太熟悉,暫時還不知道該怎麼做,可能有時間找個方法搞定它。

沒有啦……

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章