如何用堆棧來保存和恢復滾動條位置

問題背景

在單頁應用中,翻頁通常經過display:none將先前的面板(通常就是個div容器)隱藏,而後將本次須要展示的面板設置成display:block(固然,還可能加點css切換動畫,不過不影響咱們本次的討論結果,故不予關注),通常狀況下,這樣的處理方式是沒啥問題的,不過若是以前的面板自己有滾動條,那麼跳轉到新面板以後再返回到原先面板就會致使滾動條位置直接變成0,這主要是當元素的display爲none時,元素不佔據位置,等到display非none的時候纔會被從新佈局,渲染。css

咱們以jq.ui(一個用於構建jqMobi應用的用戶界面庫)爲例說明下怎麼解決單頁應用中切換頁面致使的滾動條位置信息丟失問題算法

思路

在老頁面被display:none以前用一個堆棧存儲下當前頁面的滾動條位置,而後在用戶點擊瀏覽器返回按鈕的時候取出棧頂記錄的滾動條位置信息並調用window.scroll滾動到指定位置便可。數組

基於jq.ui的實例

一、在jq.ui源碼中頁面切換以前手動觸發個事件(用於在本身的代碼中捕捉此事件並記錄老頁面滾動條位置信息)瀏覽器

/*在老的panel被display:none以前觸發beforeHideOldPanel事件,
*用於記錄當前滾動條位置,以便於返回上一頁時滾動到指定位置*/
jq(oldDiv).trigger('beforeHideOldPanel');
複製代碼

二、在頁面上監聽第一步中觸發的beforeHideOldPanel事件和popstate(瀏覽器回退事件)以及loadpanel(加載面板事件),當beforeHideOldPanel事件被觸發且當前不在回退時記錄滾動條位置,當loadpanel事件被觸發且當前正在回退時從堆棧中取出滾動條位置並調用window.scroll手動滾動到指定位置bash

// 因爲jq.wow.js中經過display:none方式切換面板,致使老的panel滾動條信息丟失
// (display:none元素無高度),點擊返回上一頁時會自動定位到頂部
// 此處經過一個簡單的堆棧記錄老頁面的滾動條信息,退回上一頁時手動調用window.scroll滾動到指定位置
function resetScrollWhenPopstate() {
    //藉助數組實現個簡單的堆棧
    var scrollStack = {
        list: [],
        push: function (obj) {
            this.list.push(obj);
        },
        pop: function () {
            return this.list.pop();
        }
    };
    
    $('.panel').on('beforeHideOldPanel', function (e) {
        // 僅非回退時才記錄滾動條位置
        if (!isPopStating) {
            scrollStack.push({
                oldPageId: e.currentTarget.id,
                oldScrollTop: document.documentElement.scrollTop || document.body.scrollTop
            });
        }
    }).on('loadpanel', function (e) {
        // 僅回退頁時才恢復滾動條位置
        if (isPopStating) {
            var obj = scrollStack.pop();
            if (obj && obj.oldPageId == e.currentTarget.id) {
                window.scroll(0, obj.oldScrollTop);
            }
        }
    });
    
    // 標示是否正在回退
    var isPopStating = false;
    window.addEventListener('popstate', function () {
        isPopStating = true;
        setTimeout(function () {
            isPopStating = false;
        }, 200);
    });
}
複製代碼

總結

看似簡單的堆棧其實仍是有挺大用處的,算法和數據結構這東西看來仍是須要學習學習(@ο@) 哇~數據結構

相關文章
相關標籤/搜索