咱們先看一個實際例子:前端
點擊菜品詳情,按返回直接退出了店鋪,這個例子還不是明顯,在有不少小店鋪的點單系統,連購物車都是一個純組件,我進入購物車,按返回直接就退出頁面了,更噁心有的沒作記錄,再次進去就空了vue
哪怕是各大廠的移動端應用也常常會看到這種尷尬的交互,這類的彈窗組件,在pc端,由於窗口足夠大,一般也會有在右上角有關閉❌按鈕,用戶也習慣與這種操做,git
但在vue移動端項目中,這類型,例如選擇框/搜索框,比較主流的交互方式是,點擊遮罩或者下方❌關閉,這種交互還算okgithub
可是有一些極端的狀況下,咱們可能須要整個彈窗是全屏幕,例如帶搜索的選擇組件,例如國籍/地址等算法
最開始,使用純組件,v-show展現bash
這種狀況下,在用戶的意識裏,已經切換了頁面 因此在安卓用戶想返回的話,會下意識點物理返回 這時候就悲劇了,直接回到了上一頁,而不是關掉當前激活的組件,測試直接給我提了一堆bug微信
基於這一點,最開始是用子路由思路作,這幾乎完美解決保留完整的頁面狀態並跳轉出一個新路由app
只是依然存在一個嚴重反作用,全部子路由公用一個router-view,若是經過這個標籤傳參的話,子路由多了的狀況下,不免會存在重名問題,固然是你本身設計的組件,經過前綴來解決也並不是不可ide
而且隨着愈來愈多的頁面使用,就發現寫法臃腫,這種情況持續大半年,隨着業務量增長,須要嵌套子路由愈來愈多,大量重複的代碼也很是難看。單元測試
終於開始着手作一些改動了
這過程考慮過的思路:
最終肯定的方案是插件式調用結路由哈希建立一條記錄,主要代碼以下:
let $vm
let $watcher
export function createDOM () {
if (typeof document === 'undefined') {
return
}
const MyComponent = Vue.extend(component)
const $vm = new MyComponent({
el: document.createElement('div')
})
document.body.appendChild($vm.$el)
return $vm
}
export function install () {
if (!$vm) {
$vm = createDOM()
Vue.prototype.$plugin = obj
}
}
export function show (options) {
const { cb } = options
if (cb) {
$vm.cb = cb
}
listening(hide)
const { path, query, params } = router.currentRoute
router.push({
path,
query,
params,
hash: 'pluginHash'
})
$watcher && $watcher()
$watcher = $vm.$watch('targetValue', (val) => {
if (val === false) {
hide()
$watcher && $watcher()
}
})
$vm.targetValue = true
}
export function hide () {
$vm.targetValue = false
$vm.$nextTick(() => {
$watcher && $watcher()
$watcher = null
if (window.location.hash.indexOf('pluginHash') !== -1) {
router.go(-1)
}
})
}
複製代碼
這是還有一點反作用的,和子路由同樣會在history最前端建立了一條記錄,尤爲是微信7.0後,把前進後退按鈕搬到下面了,若是用戶點前進的話仍是有點尷尬的,history並無給咱們提供相似pop的方法,但至少調用起來很方便,也不會有太多莫名的子路由嵌套。 你們有什麼好的套路,也能夠在評論區一塊兒交流,
但就目前來看,愈來愈多的安卓機加入全面屏的陣營,取消了物理返回健,當全面屏成爲主流,對於前端來講倒也省去不少這類的交互問題
最近由於項目遷移升級,再加上搬家之類的私事,停下了小白路的更新,不過不要緊,預計兩週後會恢復正常更新,順便預告下,小白路的第一個小遊戲是掃雷已經完成了,還在優化中,下一次大可能與算法或單元測試相關,但願後面的能給你們帶來更多幹貨