列表頁到詳情頁,從詳情頁返回之前列表頁的位置
背景:
對於一般採用同樣的技術棧開發的多頁面應用來說,可能遇到的狀況如下:
- h5上拉重新整理來實現分頁,當有很多頁的話,點選列表某一頁去詳細,然後從詳情返回上一頁,可能重新整理上一頁,位置不能保持,體驗不好
- 列表使用a連結過去的,詳情使用window.history.go(-1)返回,有些瀏覽器不重新整理上一頁(ios中safari,UC等),有些頁面重新整理上一頁(ios中微信等)
- 有說使用單頁的話,可以保持。但是之前用過angular1.X來實現單頁,返回貌似也有這個問題(重新執行了列表js),最近在github看到有用vue實現了這個的效果:https://github.com/lzxb/vue-cnode?from=xitu
- 有說列表用window.open,詳情用window.history.go(-1),h5實踐了,不可以,見上一篇。
- 之前還想過用iframe標籤,但是這隻適合用於iframe嵌入的頁面可進入的下級頁面有限,不會再回到列表頁面,或者就是一個預覽性的小頁面。
實際專案中遇到的問題
基於以上背景中的一些方法,除了提到的一些弊端,還只適合於簡單的從詳情頁到列表頁不需要更新列表頁資料的情況,如果是需要更新列表頁資料就需要考慮怎樣把要更新的某一條資料的標誌傳到列表頁,列表頁再通過ajax請求最新的資料。
在實際中遇到的專案是原來的php專案用vue重構,列表頁等部分頁面是vue單頁應用,詳情頁因為考慮seo的問題依然是php頁面,這就導致兩個完全不同的技術棧的頁面之間是完全獨立的,背景中提到的開啟新視窗的頁面對於pc端和安卓手機的主流瀏覽器都是可行的,但是對於微信瀏覽器和iphone中的大部分國內瀏覽器都是預設不執行新視窗開啟的。本來想用直接關掉新視窗重現列表頁的方法還是不夠好,特別是對於微信瀏覽器這種手機端比較大的流量入口來說,無論怎樣都會重新整理列表頁,根本達不到我們想要的效果。
因此,後面才想著把當點選列表頁的時候,把列表頁整個資料都存在客戶端,當再次返回到列表頁的時候,通過判斷是否存在資料來確定是否需要載入新的資料,如果有資料直接將頁面顯示出來,然後定位到之前儲存的scrolltop值得位置。
這種方法當然解決了手機各個瀏覽器直接新視窗開啟的相容性問題,唯一的弊端就在於可能要儲存的資料量有點大,並且資料儲存在客戶端可能存在的一些安全風險。
還有當時遺留的怎樣判斷是從詳情頁返回的問題,後來在github上面看到設定錨點的方法,大體的思路跟我想的一致。只不過我的是vue裡面,因此我是把整個data資料轉成字串儲存了下來。錨點的具體實現方式是在列表頁滾動的時候記錄頁面的scroll-top值,然後把scroll-up的值設定錨點如(#scrollY = scroll-top)這樣如果是返回的頁面就可以在列表頁獲取到hash,hash存在就可以判斷是從詳情頁返回的頁面,如果是從其他頁面通過連結進入的就直接新請求資料,更新列表頁。
一些說明
- 列表滾動使用錨點獲取scrollTop值,標誌是否返回了列表
- localStorage有過期時間,不用sessionStorage主要是因為有些安卓機的瀏覽器,跳頁面會獲取不到sessionStorage值,比如UA:Mozilla/5.0 (Linux; U; Android 5.0.2; zh-CN; Redmi Note 2 Build/LRX22G) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/40.0.2214.89 UCBrowser/11.2.0.880 Mobile Safari/537.36
- 只有返回列表才執行本地資料,index.html到list.html會重新請求資料。
- 缺點就是會將列表頁的資料都記錄下來,資料的風險性。
https://luchanan.github.io/detail2list/index.html 類似的github上的一個專案示例,非常感謝分享啦
其他的聯想
可能的解決方案:
- 改互動方式,把上拉重新整理改為類似美團美食h5那樣,手動點下一頁,稍微簡單些,這樣每次都只記錄頁碼和滾動的位置就好了(但是一般產品不會同意)
- 列表記錄當前頁碼,到頂部請求上一頁,到底部請求下一頁。(好麻煩,先放棄,位置也不準確了)這種就是資料請求很混亂。
最後附上自己測試過的vue頁面中使用的程式碼: