在寫移動端時,由於須要給頁面作轉場動畫,便有了此次的研究html
其中最主要的時如下兩個問題:vue
除了上面兩個問題,其他的操做都是能夠在頁面內進行設置,基本都是可控的。主要就是解決上面兩個問題。ios
能夠看下實際寫出來的效果:在線DEMOgit
經過記錄 歷史記錄 來比較判斷前進仍是後退github
A頁面 -> B頁面 -> C頁面
假如我從 A頁面到 B頁面 再到C頁面,歷史記錄就會產生3條數組
咱們用一個數組表示: ['/a', '/b', '/c']
瀏覽器
而後我在經過點擊瀏覽器導航欄的後退按鈕, 我便會回到 B 頁面, dom
這時候我只要判斷是否存在 B頁面, 存在就證實我點的時後退按鈕。函數
而後只要我後退過, 我就能點擊瀏覽器的前進按鈕了。這時候怎麼判斷它究竟是前進的呢。動畫
咱們能夠這樣。
當咱們後退到了B頁面,歷史記錄不是還保存着['/a', '/b', '/c']
三個路徑嗎
咱們能夠刪除B頁面後面的路徑,那如今就是 ['/a', '/b']
;
若是咱們後退到A頁面, 那麼咱們保存的路徑就是['/a']
只要咱們點擊前進按鈕, 咱們去保存的路徑裏面找, 是否是就找不到路徑了, 那樣就完成了前進判斷。
上面是一種正常的狀況。
可是假如咱們有點頁面重複進入了呢。
A頁面 -> B頁面 -> C頁面 -> B頁面 -> C頁面
如今走了5步,到達了第二個C頁面, 而後咱們後退一步,到達了B頁面
這個時候問題就出來了,咱們是刪除第一個B頁面後面的路徑仍是刪除第二個B頁面後面的路徑
['/a', '/b', '/c', '/b']
。['/a', '/b']
,這個時候咱們在此點擊後退按鈕,就會到C頁面, 可是保存的路徑裏面 `'/c'` 已經被我刪除了, 因此判斷出來的是前進。
因此以目前來看,最好的辦法就是記錄每個頁面,可是每一個頁面,都讓他有區別
那麼咱們就能夠在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左滑返回的切換。
基本上遇到的比較麻煩的兩個點就是上面這兩個點了,其他都是能夠經過監聽事件進行設置,倒也沒什麼難度