當前位置:
首頁 > 最新 > hash模式下Vue-router頁面返回錨點實現

hash模式下Vue-router頁面返回錨點實現

在普通頁面中,點擊瀏覽器的返回按鈕,在返回到上一頁時會處在上次瀏覽的位置。單頁面應用中,由於始終是同一個頁面, 因此需要自行實現頁面返回時的錨點。Vue-router的Scroll Behavior可以用於解決這個問題,但是只能應用在HTML5 history模式。本文實現了在hash模式下的錨點跳轉。

錨點位置存儲

Vue-router要求在HTML5 history模式下,是為了使用pushState、replaceState API以及popstate事件:

參考源碼html5.js

// Vue-router中的push方法 push (location: RawLocation, onComplete?: Function, onAbort?: Function) { const { current: fromRoute } = this this.transitionTo(location, route => { pushState(cleanPath(this.base + route.fullPath))// 存儲頁面錨點位置 handleScroll(this.router, route, fromRoute, false) onComplete && onComplete(route) }, onAbort) }// pushState方法 export function pushState (url?: string, replace?: boolean) { saveScrollPosition() // try...catch the pushState call to get around Safari // DOM Exception 18 where it limits to 100 pushState calls const history = window.history try { if (replace) { history.replaceState({ key: _key }, , url) } else { _key = genKey() history.pushState({ key: _key }, , url) } } catch (e) { window.location[replace ? replace : assign ](url) } }export function setupScroll () { window.addEventListener( popstate , e => { saveScrollPosition(); if (e.state && e.state.key) { setStateKey(e.state.key); } }) } window.addEventListener( popstate , e => { this.transitionTo(getLocation(this.base), route => { if (expectScroll) { handleScroll(router, route, this.current, true) } }) })

在hash模式下需要我們自己記錄錨點位置。可以維護一個與history相同的數組,每次頁面跳轉時在Vue-router提供的鉤子函數中遍曆數組,存儲錨點位置。

錨點滾動

// wait until re-render finishes before scrolling router.app.$nextTick(() => { let position = getScrollPosition(); const shouldScroll = behavior(to, from, isPop ? position : null); if (!shouldScroll) { return; } const isObject = typeof shouldScroll === object ; if (isObject && typeof shouldScroll.selector === string ) { const el = document.querySelector(shouldScroll.selector); if (el) { position = getElementPosition(el); } else if (isValidPosition(shouldScroll)) { position = normalizePosition(shouldScroll); } } else if (isObject && isValidPosition(shouldScroll)) { position = normalizePosition(shouldScroll); } if (position) { window.scrollTo(position.x, position.y); } })

我們目前已經自行記錄了錨點,因此可以在router中模仿一個跳轉過程:

router.beforeEach((to, from, next) => { next(); // 重要的是設置跳轉的時機。過早的話頁面還沒載入完成,高度不夠導致不能滾動。過晚的話會造成頁面的閃爍。 router.app.$nextTick(() => { // 獲取history數組中的最後一個browserHistoryLast if (to.fullPath === browserHistoryLast.path && browserHistoryLast.pos) { document.body.scrollTop = browserHistoryLast.pos; } else { document.body.scrollTop = 0; } }); });

在router的鉤子函數中,調用next之後,在$nextTick中進行頁面的滾動,即可達到和scrollBehavior相似的效果。

需要注意的是,各個頁面的數據應當存儲在vuex中,不能每次進入頁面都發送請求(即使不錨點也應當這麼做)。否側因為返回時頁面還在請求數據,不能達到錨點的效果。

關於過場動畫

如果頁面跳轉有過場動畫存在,非常容易在錨點滾動時發生閃爍。嘗試了幾種方式,都沒能達到很好效果。

嘗試過的方法的思路在這裡記錄一下,這些方法都會有很大的抖動閃爍,根本原因還是頁面跳轉的時機不對:

返回到有存儲pos的舊頁面時,在 中將頁面滾動到記錄的位置。打開新頁面時,在 中將頁面滾動設置為0,確保新頁面在頂部。

vue-router的過渡動畫使用的是absolute定位+transform。因此嘗試了給頁面設置top值來消除閃爍。在跳轉前給當前頁面設置與目標頁面滾動位置相同的top值,在滾動結束後由於不再是absolute定位,top值不再生效,沒有閃爍發生。在返回時,列表頁會首先絕對定位到首頁要滾動的位置(此時會有閃爍),之後直接跳轉到首頁。閃爍集中在返回過渡效果之前。

其他問題

全局mixin中不能寫組件中的過渡鉤子,如 等,會報錯。

這個issue中說已經修復了mixins usage are fixed in fb32ccb, 但是還是用不了。

computed只有在vuex中的變數變化時,才會進行更新。import進來的值不行。

在onTransitionBeforeStart修改變數,不會使from頁面中的computed更新。如果想要在頁面跳轉時更新from頁面的computed,需要在router的鉤子函數中進行修改,在this.$nextTick中調用next()。

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 推酷 的精彩文章:

索尼 SRS-XB30 體驗:真正的「跑馬燈」+ 純正的「動次打次」
重構 - 讀書筆記
[原]談一談閉包
Webapp執行reload後內存泄漏之SSLSocketFactory
提升生活品質的良品

TAG:推酷 |

您可能感興趣

內地搶購頁面已經釋出!Virgil Abloh x Nike Blazer Mid明日抽籤!
藉助AI Google Drive改善Shard with Me頁面
Selenium及Headless Chrome抓取動態HTML頁面
jQuery Mobile 頁面
WordPress登錄頁面美化插件:Login Designer
Coinmarketcap將Bitcoin.com從BTC頁面移除據,Coincheck針對新經幣被盜事件致歉
快速搭建你的 github pages 個人博客——基於 Create-React-App 的單頁面應用實踐
用了Google Play Instant功能的遊戲,商店頁面點擊量上漲1/4
CoinMarketCap悄悄地從BTC頁面中刪除Bitcoin.com
vue Router在新標籤打開頁面的實踐
Steam頁面顯示Valve Index和Knuckles將於6月15日發貨
SpringBoot整合MyBatis,MySql之從前台頁面到資料庫的小Demo
移動端兼容問題:解決ios瀏覽器history.back頁面不刷新
Intellij idea集成的git頁面進行操作
Falcom公布神秘新游「Project N.O.X」倒計時頁面
iPhone 9、iPhone XS及Max的預購頁面
Facebook封殺英國反穆斯林團體Britain First頁面
GitHub 改版,重構頁面移除了 jQuery?
iOS13與iPad OS官方頁面上線 Apple Watch將可獨立更新系統
eBay賣家Facebook營銷指南:在Facebook頁面上上傳什麼?