最近在開發公司hybrid app的時候,需要將原本原生的配置中心模塊統一變更為H5,做完之后從測試那里反饋回來這樣一個問題,當滑到頁面底部或中部的時候進入子頁面進行設置,返回的時候頁面應該定位到離開時候的位置,就是不要回到頁面頂部,體驗要接近原生。
提出的解決方案:在react生命周期的componentWillUnmount階段獲取當前滾動條的滾動距離,並且將這個數值存儲在sessionStorage中,然后在componentWillMount階段獲取之前存儲在sessionStorage中當前頁面滑動條距離頂端的問題,然后開始采用window.scrollTo方法將當前頁面滾動到之前頁面停留的位置,即可實現需求。由於這個配置中心模塊只有主頁面是特別長的需要做這個操作,其他子頁面都很短,因此不必考慮會對其他H5頁面造成干擾。在chrome上調成手機模式自測沒有問題,體驗很好,遂上傳代碼,以為完美的解決了這個問題。然而,實踐是檢驗真理的唯一標准,在打包構建放到stg環境上之后,用安卓手機自測發現報錯:scrollTo is not a function,原來安卓的上元素不支持scrollTo的方法。
正確方案:后經反復試驗,采用了一個更加周密、可靠的解決方案。首先在組件上監聽一個滾動事件。即在componentWillMount階段使用原生js監聽滾動,
document.addEventListener('scroll', this.e.onScrollHandle, false);
constructor中也要注冊一下這個方法:
this.e = {
onScrollHandle: this.onScrollHandle.bind(this)
};
具體的滾動事件,將其滾動位置實時記錄下來
onScrollHandle(event) {
const scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
localCache.setItem('_device_setting_scroll_' + PAGE_PARAMS.deviceId, scrollTop);
}
此處采用了localCache本地緩存作為存儲容器,並且根據當前配置頁面的deviceId作為標志位作了區分,防止記錄上一台設備的設置頁面的滾動位置而影響到下一台設備的設置頁面的滾動位置。
在componentDidMount階段取出記錄的滾動條滾動位置,並開始滾動到指定位置,滾動到指定位置后移除記錄的key,若用戶又開始滾動,則又開始記錄,若用戶不再滾動,只是打開看一眼,則下次頁面會置頂。
let cacheKey = '_device_setting_scroll_' + PAGE_PARAMS.deviceId;
localCache.getItem(cacheKey).then((scrollTop) => {
if(scrollTop){
document.body.scrollTop = document.documentElement.scrollTop = scrollTop || 0;
}
localCache.removeItem(cacheKey);
});
最后,在componentWillUnmount階段移除監聽事件:
document.removeEventListener('scroll', this.e.onScrollHandle);
經測試,IOS和安卓手機都達到了預期效果,圓滿修復了此bug。