解決Vue頁面固定滾動位置的處理辦法
最近做項目遇到一個問題,就是Vue滾動不固定,網(wǎng)上找了一些資料,說下 vue 固定滾動位置的處理辦法.
問題描述:
通常見于 列表頁List -> 詳情頁Detail 的情況, 從列表的某一項x 進(jìn)入到詳情頁, 再返回的時候, 希望列表的位置固定在x, 而不是回到頂部了.
vue-router 里面是有一個 scrollBehavior 的, 但是這個玩意只能在 history 模式下面使用, 而我用的 hash 模式.
所以我們要自己實現(xiàn)嘛, 思路簡單:List 里面監(jiān)聽滾動, 記錄滾動位置 pos, 從 Detail 返回到 List 里面的時候, 讀取 pos.
mounted () {
// 讀
setTimeut(function(){
document.body.scrollTop = parseInt(sessionStorage.getItem('pos'));
}, 1000);
// 存
window.onscroll = function () {
sessionStorage.setItem('pos', document.body.scrollTop);
}
}
遇見了一個問題:
每次返回 List, 都是直接滾動到頂部, 每次都是, 每次都是! 把 pos 打印出來, 發(fā)現(xiàn)是 0, 而不是我們所存的值. 日了, 明明切換之前還是的, 回來就不是了.
然后發(fā)現(xiàn)了路由每次切換都會觸發(fā) onscroll 事件, 日了狗, 為毛.我都沒有滾動頁面, 為什么會觸發(fā) onscroll 事件。
剛開始懷疑 hash 變化會導(dǎo)致 onscroll 事件的觸發(fā), 所以我就在瀏覽器里面手動輸入了幾個不存在的路由:
/foo /bar
沒有發(fā)現(xiàn) scroll 被觸發(fā), 所以這個嫌疑排出.
然后懷疑 vue-router 里面是不是綁定了 scroll 事件, 沒發(fā)現(xiàn)然后又想, 沒綁定 scroll 事件, 那么修改 scrollTop 值會不會也觸發(fā) scroll 事件.
好吧還發(fā)現(xiàn)新知識點了:
scrollTop 值的改變, 的確會觸發(fā) scroll 事件.
那么我就想, 是不是 vue-router 里面存在修改 scrollTop 值的行為, 也沒有發(fā)現(xiàn).
然后我又想, 數(shù)據(jù)是動態(tài)渲染的, 所以是不是和元素的增刪改查相關(guān)。
元素增加-> 頁面高度變了 -> 頁面高度變化, 也觸發(fā) scroll 事件?
所以我用 vue-cli 新建了項目, 放了兩個沒有增刪改查的路由
然后日了狗的, 我看見從 foo -> bar -> foo, 的時候, foo的滾動條位置還在之前我滾動到的地方.
突然想起來瀏覽器是可以自己記錄滾動條位置的.
是不是瀏覽器干的?
從詳情頁返回到列表頁面, 列表會重新渲染, 時序大概是這樣:
返回列表頁 1
渲染頁面 2
而瀏覽器恢復(fù)滾動條的位置的操作, 是在 1 和 2 之間, 這個時候就出問題了:如果你頁面上面的數(shù)據(jù)都是渲染出來的, 瀏覽器就會發(fā)現(xiàn):
頁面的高度<=屏幕的高度, 不存在滾動條, 此時 document.body.scrollTop = 0;
所以會設(shè)置 document.body.scrollTop = 0
修改了 document.body.scrollTop 觸發(fā)了 scroll 事件, scroll 里面又重寫了 pos
等你數(shù)據(jù)渲染結(jié)束之后, 讀到的就是 0了.
如果發(fā)現(xiàn)你頁面高度大于屏幕高度, 但是頁面高度是 n, 而 pos 的值是: n + x, 比當(dāng)前頁面的最大的 scrollTop 值還大, 這個時候, document.body.scrollTop 的值就會等于 n.
當(dāng)你的數(shù)據(jù)渲染結(jié)束, 開始定位, 日了, 沒定準(zhǔn).
所以我們要解決這個問題.
當(dāng)然是想到了 keep-alive, 剛啟用的時候, 發(fā)現(xiàn)的確不錯. 但是同時也發(fā)現(xiàn):
列表項目靠前的, 往返操作的定位都很準(zhǔn), 越往后越不行, 直接拉到底, 再返回發(fā)現(xiàn)定位到的一般都是第二個第三個列表項目.
所以這個就很有意思了, 我大概猜測了一下瀏覽器的滾動位置恢復(fù)行為:
當(dāng) hashchange 的時候。拿到當(dāng)前頁面的 document.body.scrollTop 值, 和自己存儲的滾動條位置。二者取最小的值, 設(shè)置成當(dāng)前的 document.body.scrollTop 的值, 當(dāng)使用 keep-alive 的時候, 因為 hashchange 事件處理和頁面渲染是并行的, 所以有時hashchange 拿到的 document 的高度是已經(jīng)渲染過幾個元素的高度, 這個就是為什么定不準(zhǔn)的原因.
好吧, 現(xiàn)在的情況是:
keep-alive 定不準(zhǔn), 不可靠, 所以需要我們自己來重新定位.
ok, 1 先綁定 scroll 事件:
var map = {};
window.onscroll = function() {
map[location.hash] = document.body.scrollTop;
}
2 再屏蔽掉瀏覽器自動恢復(fù)滾動位置行為帶來的影響
a 在 hashchange 時強(qiáng)制 document.body.scrollTop = 0
b 在 scroll 事件里面, 當(dāng) document.body.scrollTop = 0 的時候不做 存操作.
var map = {};
window.onhashchange = function() {
document.body.scrollTop = 0;
}
window.onscroll = function() {
if (document.body.scrollTop) {
// 存
map[location.hash] = document.body.scrollTop;
} else {
// 讀
}
}
3 在讀操作里面, 設(shè)置一個定時任務(wù), 去判斷 document.body.scrollTop 的值和你保存的位置是不是相同的
var map = {};
window.onhashchange = function() {
document.body.scrollTop = 0;
}
window.onscroll = function() {
if (document.body.scrollTop) {
// 存
map[location.hash] = document.body.scrollTop;
} else {
var timer = null;
timer = setInterval(function(){
if (document.body.scrollTop == map[location.hash]) {
clearInterval(timer);
} else {
document.body.scrollTop = map[location.hash];
}
}, 20);
}
}
到這里實際上已經(jīng)大體實現(xiàn)了, 返回恢復(fù)滾動條位置的功能, 而上面的代碼需要更多的優(yōu)化,
具體代碼見:項目地址
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- Vue實現(xiàn)渲染數(shù)據(jù)后控制滾動條位置(推薦)
- vue實現(xiàn)滾動條到頂部或者到指定位置
- vue中實現(xiàn)點擊按鈕滾動到頁面對應(yīng)位置的方法(使用c3平滑屬性實現(xiàn))
- vue監(jiān)聽頁面中的某個div的滾動事件并判斷滾動的位置
- Vue滾動到指定位置的多種方式示例詳解
- Vue滾動頁面到指定位置的實現(xiàn)及避坑
- Vue列表如何實現(xiàn)滾動到指定位置樣式改變效果
- 解決vue無法設(shè)置滾動位置的問題
- vue通過滾動行為實現(xiàn)從列表到詳情,返回列表原位置的方法
- vue-scroller記錄滾動位置的示例代碼
- Vue頁面返回滾動位置恢復(fù)(keep-alive滾動記憶)
相關(guān)文章
為vue中的data賦值computed計算屬性后,出現(xiàn)undefined原因及解決
這篇文章主要介紹了為vue中的data賦值computed計算屬性后,出現(xiàn)undefined原因及解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-07-07
vue內(nèi)置動態(tài)組件component使用示例小結(jié)
component是vue內(nèi)置組件,主要作用為動態(tài)渲染組件,這篇文章主要介紹了vue內(nèi)置動態(tài)組件component使用示例小結(jié),需要的朋友可以參考下2024-03-03
安裝vue3開發(fā)者工具但控制臺沒有顯示出vue選項的解決
這篇文章主要介紹了安裝vue3開發(fā)者工具但控制臺沒有顯示出vue選項的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-10-10
el-table實現(xiàn)搜索高亮展示并滾動到元素位置的操作代碼
這篇文章主要介紹了el-table實現(xiàn)搜索高亮展示并滾動到元素位置,本文通過示例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友參考下吧2024-01-01
VUE前端實現(xiàn)防抖節(jié)流Lodash工具庫舉例詳解
這篇文章主要介紹了Lodash庫和自定義防抖、節(jié)流函數(shù)的使用方法,包括它們的定義、應(yīng)用示例及應(yīng)用場景文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下2025-01-01
使用Vue-Awesome-Swiper實現(xiàn)旋轉(zhuǎn)疊加輪播效果&平移輪播效果
這篇文章主要介紹了用Vue-Awesome-Swiper實現(xiàn)旋轉(zhuǎn)疊加輪播效果&平移輪播效果,代碼簡單易懂,非常不錯,具有一定的參考借鑒價值需要的朋友可以參考下2019-08-08

