vue移動端路由切換實例分析
在寫移動端時,因為需要給頁面做轉(zhuǎn)場動畫,便有了這次的研究
其中最主要的時以下兩個問題:
瀏覽器導(dǎo)航欄的切換
IOS 上滑動切換時,會有兩次頁面的轉(zhuǎn)場動畫,一次自身滑動時進(jìn)行的切換,隨后觸發(fā)我們設(shè)置的轉(zhuǎn)場動畫。
除了上面兩個問題,其余的操作都是可以在頁面內(nèi)進(jìn)行設(shè)置,基本都是可控的。主要就是解決上面兩個問題。
可以看下實際寫出來的效果:在線DEMO
1. 瀏覽器導(dǎo)航欄的切換
通過記錄 歷史記錄 來比較判斷前進(jìn)還是后退
如下例子
A頁面 -> B頁面 -> C頁面
假如我從 A頁面到 B頁面 再到C頁面,歷史記錄就會產(chǎn)生3條
我們用一個數(shù)組表示: ['/a', '/b', '/c']
然后我在通過點擊瀏覽器導(dǎo)航欄的后退按鈕, 我便會回到 B 頁面,
這時候我只要判斷是否存在 B頁面, 存在就證明我點的時后退按鈕。
然后只要我后退過, 我就能點擊瀏覽器的前進(jìn)按鈕了。這時候怎么判斷它到底是前進(jìn)的呢。
我們可以這樣。
當(dāng)我們后退到了B頁面,歷史記錄不是還保存著['/a', '/b', '/c'] 三個路徑嗎
我們可以刪除B頁面后面的路徑,那現(xiàn)在就是 ['/a', '/b'];
如果我們后退到A頁面, 那么我們保存的路徑就是['/a']
只要我們點擊前進(jìn)按鈕, 我們?nèi)ケ4娴穆窂嚼锩嬲遥?是不是就找不到路徑了, 那樣就完成了前進(jìn)判斷。
上面是一種正常的情況。
但是假如我們有點頁面重復(fù)進(jìn)入了呢。
就如以下這種情況
A頁面 -> B頁面 -> C頁面 -> B頁面 -> C頁面
現(xiàn)在走了5步,到達(dá)了第二個C頁面, 然后我們后退一步,到達(dá)了B頁面
這個時候問題就出來了,我們是刪除第一個B頁面后面的路徑還是刪除第二個B頁面后面的路徑
我們先試著刪除第二個B頁面的路徑,那么我們還保存的路徑就是: ['/a', '/b', '/c', '/b']。
1、那這個時候我們按照上面正常情況的邏輯來操作.
我點擊前進(jìn), 然后我去保存的路徑里面找,找不到就算前進(jìn), 找到證明是后退。
那么結(jié)果顯而易見,我們找到了第一個C頁面,那就這樣就算后退了,但其實我點擊的時前進(jìn)
2、那我們試著刪除第一個B頁面后面的路徑,那么保存的路徑就是: ['/a', '/b'],
那么我在點擊后退按鈕,這時候他其實會進(jìn)入C頁面, 我們可以看以下流程圖
這個時候我們在此點擊后退按鈕,就會到C頁面, 但是保存的路徑里面 `'/c'` 已經(jīng)被我刪除了, 所以判斷出來的是前進(jìn)。
1、如果我們過濾重復(fù)的頁面路徑,是不是就會好了呢,其實也是一樣的
假如我們有5個頁面路徑,過濾了2個重復(fù)的,只有3個頁面路徑了
那么我退到第四個路徑的時候是不是就找不到了, 那么后面兩個頁面都會算作前進(jìn)。
所以以目前來看,最好的辦法就是記錄每一個頁面,但是每個頁面,都讓他有區(qū)別
那么我們就可以在url上面放一個隨機(jī)字符串
代碼實現(xiàn):
// 當(dāng)沒有key的時候會進(jìn)入兩次 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) { // 當(dāng)前路徑是最后一條,證明是同一個頁面 console.log('refresh') } else { // 后退 store.commit('UPDATE_ROUTER_DIRECTION', { routerDirection: 'back' }) // 后退標(biāo)志 store.commit('DELETE_NAVIGATION', { index: toIndex }) // 刪除當(dāng)前路徑后面的路徑 } }else{ // 不存在該路徑 store.commit('UPDATE_ROUTER_DIRECTION', { routerDirection: 'forward' }) // 前進(jìn)標(biāo)志 updateNavigations(to) // 保存該連接 } const query = { ...to.query } // 存在就直接next, 防止死循環(huán) 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 的隨機(jī)串,那樣就算同一個頁面在我們保存的路徑里面也是其實是不同的。就可以正常的執(zhí)行邏輯了
上面就基本解決了瀏覽器導(dǎo)航欄的問題了
2. IOS上的滑動切換
在IOS的網(wǎng)頁上, 是可以左右滑動進(jìn)行切換,即使你沒有做轉(zhuǎn)場動畫。
這個時候就會出現(xiàn)一個問題。
還是ABC頁面
A -> B -> C
當(dāng)我們到達(dá)C頁面,然后向左滑動時,滑完他就進(jìn)入B頁面,但是這這時它還是會進(jìn)入我們的 beforeEach 這個鉤子函數(shù)里面,執(zhí)行我們上面的邏輯。
那樣就會觸發(fā)我們的轉(zhuǎn)場動畫。你就會發(fā)現(xiàn)執(zhí)行了兩次切換。
于是我在網(wǎng)上找到了一種方法fix ios左滑再次執(zhí)行動畫 #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: '' }) } })
上面也很好理解, 就是我們?nèi)〉绞种缸詈箅x開的屏幕的那一刻, 然后在到 beforeEach里面進(jìn)行比較,
當(dāng)手指離開屏幕的最后一刻跟我們自己 beforeEach里面進(jìn)行的轉(zhuǎn)場相差小于 337, 就算是IOS的滑動切換
那樣就解決了IOS的滑動切換問題了。
但是IOS的右滑切換時監(jiān)聽不到手指離開屏幕的那一刻的(也不知道是什么鬼), 所以IOS的右滑切換,是沒法像上面那樣判斷的。
這個我也沒找到解決辦法, 暫時只能解決IOS左滑返回的切換。
基本上遇到的比較麻煩的兩個點就是上面這兩個點了,其余都是可以通過監(jiān)聽事件進(jìn)行設(shè)置,倒也沒什么難度
相關(guān)文章
uniapp 小程序和app map地圖上顯示多個酷炫動態(tài)的標(biāo)點效果(頭像后端傳過來)
這篇文章主要介紹了uniapp 小程序和app map地圖上顯示多個酷炫動態(tài)的標(biāo)點效果(頭像后端傳過來),本文通過示例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-09-09vue如何利用store實現(xiàn)兩個平行組件間的傳值
這篇文章主要介紹了vue如何利用store實現(xiàn)兩個平行組件間的傳值,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-04-04利用vite創(chuàng)建vue3項目的全過程及一個小BUG詳解
Vite作為一個構(gòu)建工具,提供了一種快速的方法來構(gòu)建Vue應(yīng)用,而Vue3?則是一個前端框架,提供了強(qiáng)大的功能來構(gòu)建和管理前端項目,下面這篇文章主要給大家介紹了關(guān)于利用vite創(chuàng)建vue3項目的全過程及一個小BUG的相關(guān)資料,需要的朋友可以參考下2023-04-04