咱们先看一个实际例子:前端
点击菜品详情,按返回直接退出了店铺,这个例子还不是明显,在有不少小店铺的点单系统,连购物车都是一个纯组件,我进入购物车,按返回直接就退出页面了,更恶心有的没作记录,再次进去就空了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的方法,但至少调用起来很方便,也不会有太多莫名的子路由嵌套。 你们有什么好的套路,也能够在评论区一块儿交流,
但就目前来看,愈来愈多的安卓机加入全面屏的阵营,取消了物理返回健,当全面屏成为主流,对于前端来讲倒也省去不少这类的交互问题
最近由于项目迁移升级,再加上搬家之类的私事,停下了小白路的更新,不过不要紧,预计两周后会恢复正常更新,顺便预告下,小白路的第一个小游戏是扫雷已经完成了,还在优化中,下一次大可能与算法或单元测试相关,但愿后面的能给你们带来更多干货