一種移動端模擬實現返回攔截的方案

舞動乾坤發表於2019-03-20

移動端作為網際網路重要入口,切圖仔前端工程師開發移動端頁面早已是司空見慣的事了,並且其中大部分都是內嵌於客戶端(app,小程式)的 h5頁面,即 webview

有次被同事問到一個問題,他有個需求,是一個內嵌在客戶端app內的頁面,有個功能點是攔截客戶端的返回操作,實現頁面內彈層的顯示與隱藏,攔截點包括 app頁面上自帶的返回按鈕以及安卓機的物理按鈕,類似於下面這種:

一種移動端模擬實現返回攔截的方案

點選購物車,則購物車元素從頁面底部彈起顯示,點選遮罩層,則彈層關閉隱藏,這是很正常的操作,而除此之外,還需要實現的一個功能是,點選螢幕返回鍵或者安卓機的物理返回鍵,也能夠關閉彈層,並且保證頁面不發生跳轉

我聽了微微一笑,問他,哪個傻叉 PM提的需求?,h5怎麼攔截 app甚至是物理按鈕的操作?你當時沒有懟他嗎?客戶端那邊有提供攔截返回的 sdk介面嗎?同事回答 sdk沒有提供這個能力,他覺得不好實現,但 PM堅持要做這個功能

於是我抱著反正不是我的需求,我天馬行空章口就來瞎提建議也沒關係助人為樂的態度思考了一會,誰知還真讓我想到了一個方案(我不確定以前是不是在什麼地方看到過,總之就是想到了),回來驗證了一下,確實是可行的

關鍵點在於,利用返回操作會觸發路由改變的特性來模擬達到攔截的效果,並不是真的監聽或者攔截到了螢幕返回鍵或者物理返回鍵的點選

路由配置

假設需要進行模擬攔截返回操作的主頁面路由為 /physicsBack,其下有個子路由 /physicsBack/footerModal,當路由為 /physicsBack時就只顯示頁面,當路由為 /physicsBack/footerModal時,就在 /physicsBack上彈起彈層

這裡的 /physicsBack/footerModal說起來是子路由,但實際上我們只是想利用其作為路由的一個能力——即攔截返回操作,所以實際上並不真的需要為這個路由配置一個頁面,你當然也可以這麼做,最後也能實現效果,但未免麻煩了些

這裡我將 /physicsBack/physicsBack/footerModal全部指向同一個頁面,即主頁面,然後通過對路由的監聽,來控制彈層的顯隱

路由配置如下:

 const router = new VueRouter({
  routes: [{
    path: '/physicsBack/(footerModal)?',
    component: physicsBack
  }]
 })
複製程式碼複製程式碼

/physicsBack/(footerModal)?同時匹配 /physicsBack/physicsBack/footerModal,所以無論路由是 /physicsBack 還是 /physicsBack/footerModal,都將指向 physicsBack這個頁面,達到即使路由在這兩個中來回切換,但頁面也毫無變化的目的

路由監聽

雖然在路由 /physicsBack/physicsBack/footerModal中切換不會引起頁面的切換,自始至終都停留在 physicsBack元件上,但卻可以在 physicsBack元件中對路由進行監聽,進而根據監聽到的路由變化來控制彈層的顯隱:

watch: {
  $route (to, from) {
    this.manageFooterModal(to.path, from.path)
  }
}
// ...
manageFooterModal (toPath, fromPath) {
  if (toPath === '/physicsBack/footerModal') {
    this.visible = true
  } else if (fromPath === '/physicsBack/footerModal') {
    this.visible = false
  }
}
複製程式碼複製程式碼

toPath/physicsBack/footerModal,表示將切換到這個路由,前面已經規定了,當路由切換到這個位置時,顯示彈層;

fromPath/physicsBack/footerModal,表示從有彈層的頁面回退或者跳走,則關閉彈層

除了通過路由控制之外,頁面元素肯定也必須能夠對彈層顯隱進行控制,例如點選某個元素彈起彈層,這樣才貼合真實使用場景

同樣的,由於彈層的顯隱實際上是有路由的切換控制,所以頁面內部想要改變彈層的顯隱,也必須通過路由切換來完成:

changeVisible () {
  if (this.visible) {
    this.$router.go(-1)
  } else {
    this.$router.push('/physicsBack/footerModal')
  }
}
複製程式碼複製程式碼

由於這實際上是利用了系統的返回能力,所以無論你在瀏覽器上還是客戶端 appwebview內,無論是使用螢幕返回還是物理返回鍵,都可以達到同樣的效果

實現的效果如下:

一種移動端模擬實現返回攔截的方案

做了個 Live Demo,感興趣的可以親自試下,程式碼也已經上傳到 github

小結

本文所說的通過路由來模擬攔截返回鍵的能力,不僅僅可以應用在彈層例子上,其他跟返回相關的操作理論上都可以發揮想象,例如返回重定向,禁止使用者退出頁面(這是什麼傻叉需求啊)

轉自小tips-一種移動端模擬實現返回攔截的方案

相關文章