再次學習History.scrollRestoration
之前在react.dev的源代碼中了解到了這個HIstory的屬性,當時寫了一篇筆記來記錄我對它的理解,現在看來還是一知半解。所以今天打算重新學習一下這個屬性,主要從屬性以及所屬對象的介紹、使用方法,是否開啟標準這幾個方面來簡單展開。
什么是scrollRestoration
scrollRestoration是一個屬性,它所屬的實例是瀏覽器的History。
這個屬性是做什么的?它用來控制我們在切換歷史頁面的時候,滾動條的位置會不會恢復到之前的位置。
如圖所示,我們切換歷史頁面,又切換回最之前的頁面,發現滾動條的位置依然保持底部,也就是之前的位置。
什么是切換歷史頁面,從操作上來講就是點擊瀏覽器的回退(有的瀏覽器長按回退鍵會彈出歷史的前面多個頁面供選擇)、前進按鈕
從代碼上來講就是執行下面的這些操作:
history.back()
history.forward()
history.go(page) // page大于0,表示往后面翻對應的頁數,反之則是往前翻對應的頁數
那么scrollRestoration這個屬性與是否恢復滾動條的關系是什么?
scrollRestoration可選的值為auto和manual (如果瀏覽器支持這個屬性,那么它默認是auto)
scroll restoration mode, a scroll restoration mode, initially “auto”. HTML Standard
如果是auto:那么在切換歷史頁面的時候,滾動條會自動地恢復到切換之前的位置。
如果是manual:那么在切換頁面的時候,滾動條會在頂部。
(上述的結果均在未手動修改state對應的滾動條位置的情況下)
屬性的局限性
我之前覺得這個特性很好,但是為什么要單獨地設置一個屬性來控制是否要恢復到之前的滾動條位置呢?
在History API - 滾動恢復 | Blog | Chrome for Developers這篇文章中提到:
This often means unsightly jumps as the scroll position changes automatically, and especially so if your app does transitions, or changes the contents of the page in any way. Ultimately this leads to an horrible user experience.
To make matters even worse there’s very little you can do about it: Chrome triggers apopState
event before thescroll
event, which means you can read the current scroll position inpopState
and then reverse it in thescroll
event handler withwindow.scrollTo
(Ewww, but at least it works!). Firefox, however, triggers thescroll
event beforepopState
, so you have no idea what the old scroll value was in order to restore it. Bah!
翻譯為中文:
這通常意味著當滾動位置自動改變時會出現難看的跳動,尤其是當你的應用程序進行過渡或以任何方式更改頁面內容時。這最終會導致糟糕的用戶體驗。
更糟的是,你幾乎無能為力:Chrome 會在 scroll 事件之前觸發 popState 事件,這意味著你可以在 popState 中讀取當前的滾動位置,然后在 scroll 事件處理程序中使用 window.scrollTo 恢復滾動位置(呃,但至少它能工作!)。然而,Firefox 則是在 popState 事件之前觸發 scroll 事件,所以你無法知道舊的滾動位置以便恢復它。唉!
總結一下就是,此文的作者認為這個屬性會造成的兩個缺點是:
- 可能產生不太美觀的跳躍:當滾動位置自動改變時,頁面內容可能會突然跳動,尤其是在應用程序進行過渡或更改頁面內容時,這會導致不好的用戶體驗。
- (在不開啟這個屬性的時候)非常難以人工地實現恢復滾動位置:由于不同瀏覽器在觸發 popState 和 scroll 事件的順序上存在差異(如 Chrome 和 Firefox),這使得在所有瀏覽器中一致地恢復滾動位置變得非常困難。
那么什么時候需要設置為manual?
參考上面的兩個缺點來說,當滿足以下的條件的時候,可以考慮設置為manual
- 頁面確實會產生了不太美觀的跳躍
- 不在意歷史的滾動條位置,同時更希望全部由手動控制滾動條位置的時候
參考的資料
History: scrollRestoration property - Web APIs | MDN
HTML Standard