在寫移動端時,由於須要給頁面作轉場動畫,便有了此次的研究html
其中最主要的時如下兩個問題:vue
除了上面兩個問題,其他的操做都是能夠在頁面內進行設置,基本都是可控的。主要就是解決上面兩個問題。ios
能夠看下實際寫出來的效果:在線DEMOgit
經過記錄 歷史記錄 來比較判斷前進仍是後退github
A頁面 -> B頁面 -> C頁面數組
假如我從 A頁面到 B頁面 再到C頁面,歷史記錄就會產生3條瀏覽器
咱們用一個數組表示: ['/a', '/b', '/c']
bash
而後我在經過點擊瀏覽器導航欄的後退按鈕, 我便會回到 B 頁面,markdown
這時候我只要判斷是否存在 B頁面, 存在就證實我點的時後退按鈕。dom
而後只要我後退過, 我就能點擊瀏覽器的前進按鈕了。這時候怎麼判斷它究竟是前進的呢。
咱們能夠這樣。
當咱們後退到了B頁面,歷史記錄不是還保存着['/a', '/b', '/c']
三個路徑嗎
咱們能夠刪除B頁面後面的路徑,那如今就是 ['/a', '/b']
; 若是咱們後退到A頁面, 那麼咱們保存的路徑就是['/a']
只要咱們點擊前進按鈕, 咱們去保存的路徑裏面找, 是否是就找不到路徑了, 那樣就完成了前進判斷。
上面是一種正常的狀況。 可是假如咱們有點頁面重複進入了呢。
A頁面 -> B頁面 -> C頁面 -> B頁面 -> C頁面
如今走了5步,到達了第二個C頁面, 而後咱們後退一步,到達了B頁面 這個時候問題就出來了,咱們是刪除第一個B頁面後面的路徑仍是刪除第二個B頁面後面的路徑
咱們先試着刪除第二個B頁面的路徑,那麼咱們還保存的路徑就是: ['/a', '/b', '/c', '/b']
。 那這個時候咱們按照上面正常狀況的邏輯來操做. 我點擊前進, 而後我去保存的路徑裏面找,找不到就算前進, 找到證實是後退。 那麼結果顯而易見,咱們找到了第一個C頁面,那就這樣就算後退了,但其實我點擊的時前進
那咱們試着刪除第一個B頁面後面的路徑,那麼保存的路徑就是: ['/a', '/b']
, 那麼我在點擊後退按鈕,這時候他其實會進入C頁面, 咱們能夠看如下流程圖
'/c'
已經被我刪除了, 因此判斷出來的是前進。 若是咱們過濾重複的頁面路徑,是否是就會好了呢,其實也是同樣的 假如咱們有5個頁面路徑,過濾了2個重複的,只有3個頁面路徑了 那麼我退到第四個路徑的時候是否是就找不到了, 那麼後面兩個頁面都會算做前進。
因此以目前來看,最好的辦法就是記錄每個頁面,可是每一個頁面,都讓他有區別 那麼咱們就能夠在url上面放一個隨機字符串
代碼實現:
// 當沒有key的時候會進入兩次 beforeEach,咱們只需保存帶key的就行 const updateNavigations = (to) => { if (to.query[pathKey]) { store.commit('UPDATE_NAVIGATIONS', {path: to.fullPath}) } } router.beforeEach((to, from, next) => { let toIndex = store.state.navigations.findIndex(path => path === to.fullPath) if (toIndex >= 0) { // 存在該路徑 let len = store.state.navigations.length-1 if (toIndex === len) { // 當前路徑是最後一條,證實是同一個頁面 console.log('refresh') } else { // 後退 store.commit('UPDATE_ROUTER_DIRECTION', { routerDirection: 'back' }) // 後退標誌 store.commit('DELETE_NAVIGATION', { index: toIndex }) // 刪除當前路徑後面的路徑 } }else{ // 不存在該路徑 store.commit('UPDATE_ROUTER_DIRECTION', { routerDirection: 'forward' }) // 前進標誌 updateNavigations(to) // 保存該鏈接 } const query = { ...to.query } // 存在就直接next, 防止死循環 if (!query['APP_KEY']) { // 不存在添加key ,再次 next query['APP_KEY'] = Math.random().toString(16).substring(2) next({ path: to.path, query}) }else{ next() } }) 複製代碼
以上代碼咱們就能就url中添加一個 APP_KEY
的隨機串,那樣就算同一個頁面在咱們保存的路徑裏面也是實際上是不一樣的。就能夠正常的執行邏輯了 上面就基本解決了瀏覽器導航欄的問題了
在IOS的網頁上, 是能夠左右滑動進行切換,即便你沒有作轉場動畫。 這個時候就會出現一個問題。
A -> B -> C
當咱們到達C頁面,而後向左滑動時,滑完他就進入B頁面,可是這這時它仍是會進入咱們的 beforeEach
這個鉤子函數裏面,執行咱們上面的邏輯。 那樣就會觸發咱們的轉場動畫。你就會發現執行了兩次切換。
因而我在網上找到了一種方法 fix ios左滑再次執行動畫 #2259
代碼是這樣的
let touchEndTime = Date.now() window.addEventListener('touchend', () => { touchEndTime = Date.now() }) router.beforeEach((to, from, next) => { if ((Date.now() - touchEndTime) < 377) { // ios滑動切換 store.commit('UPDATE_ROUTER_DIRECTION', { routerDirection: '' }) } }) 複製代碼
上面也很好理解, 就是咱們取到手指最後離開的屏幕的那一刻, 而後在到 beforeEach
裏面進行比較, 當手指離開屏幕的最後一刻跟咱們本身 beforeEach
裏面進行的轉場相差小於 337, 就算是IOS的滑動切換
那樣就解決了IOS的滑動切換問題了。
可是IOS的右滑切換時監聽不到手指離開屏幕的那一刻的(也不知道是什麼鬼), 因此IOS的右滑切換,是無法像上面那樣判斷的。 這個我也沒找到解決辦法, 暫時只能解決IOS左滑返回的切換。
基本上遇到的比較麻煩的兩個點就是上面這兩個點了,其他都是能夠經過監聽事件進行設置,倒也沒什麼難度