在使用 Vue.js 开发 SPA(Single-page Application)应用时,我们可能会遇到一个比较常见的问题:在安卓设备上,点击 Back 键无法返回上一页,而是直接退出应用。这种情况会给用户带来不便,降低用户体验度。那么,该如何解决这个问题呢?
问题分析
在 SPA 应用中,我们通过路由控制页面的展示,通过组件实现不同功能的模块化。对于前端开发来说,可以使用 Vue.js 提供的 Vue Router 进行路由管理。而对于移动端的用户来说,通常会习惯使用设备上的 Back 键,来快捷地返回上一页。
然而,对于安卓设备而言,Back 键的行为方式与 iOS 有所不同。在 Android 中,Back 键不仅可以返回上一页,还能直接退出应用。因此,在 Vue.js SPA 中,如果我们没有对 Android 的 Back 键做出特殊处理,就可能造成用户误操作,使得这个键不再是“返回”按钮,而时常成为“退出”按钮。
解决方案
为了解决这个问题,我们需要在 Vue.js 应用中,对安卓设备下的 Back 键做出特殊处理。具体来说,我们需要在 Vue Router 中添加额外的逻辑来控制页面的导航与历史记录。
第一步:获取操作系统类型判断是否为安卓设备
在 Vue.js 应用中,我们可以通过 navigator.userAgent
获取当前浏览器的 User Agent 字符串。根据该字符串可以判断当前运行的操作系统类型为 iOS 或是 Android。
实现代码如下:
isAndroid() { const userAgent = navigator.userAgent.toLowerCase(); return /android/i.test(userAgent); }
如果返回 true,表示当前为 Android 设备;如果返回 false,则为 iOS 设备。
第二步:监听路由变化,控制页面导航与历史记录
在路由发生变化时,在 Vue Router 中使用 beforeEach
函数来拦截路由请求,通过控制路由的跳转来实现对 Back 键的特殊处理。具体步骤代码如下:
// javascriptcn.com 代码示例 const history = window.sessionStorage; history.clear(); let historyCount = history.getItem('count') * 1 || 0; window.addEventListener('popstate', () => { const count = history.getItem('count') * 1; history.setItem('count', count - 1); historyCount = count - 1; }); router.beforeEach((to, from, next) => { const isAndroid = this.isAndroid(); history.setItem('count', historyCount); if (isAndroid) { // 在安卓下,通过修改 history 跳转路径来控制页面导航 history.setItem(`page-${historyCount}`, JSON.stringify(from)); if (to.path === from.path) { next(); } historyCount++; history.setItem('count', historyCount); // 关闭当前页面,实现类似返回上一页的效果 window.history.go(-1); } else { next(); } });
以上代码的解释:
- 在打开页面时,先清空 sessionStorage;
- 监听 popstate 事件,每次在页面跳转时,更新 sessionStorage 里记录的历史记录;
- 在 Vue Router 中使用
beforeEach
函数拦截路由请求; - 判断当前设备是否为 Android;
- 如果为 Android,通过修改 history 跳转路径来控制页面导航;
- 如果页面是从上一页返回过来的,跳过中间路由,直接展示目标页面;
- 如果不是从上一页返回而是从其他页面进入,记录历史记录;
- 关闭当前页面,实现类似返回上一页的效果。
第三步:在页面中添加 Back 键点击事件
根据安卓设备的特殊行为方式,Back 键不仅可以返回上一页,还能直接退出应用。那么,为了保证用户可以正常回到上一页,我们需要在每个页面中添加 Back 键的点击事件,来控制当前页面的退出。
实现代码如下:
// javascriptcn.com 代码示例 mounted() { document.addEventListener('backbutton', this.onBackButton, false); }, destroyed() { document.removeEventListener('backbutton', this.onBackButton, false); }, methods: { onBackButton() { const isAndroid = this.isAndroid(); if (isAndroid) { const count = window.sessionStorage.getItem('count') * 1 || 0; if (count > 1) { this.$router.go(-1); } else { navigator.app && navigator.app.exitApp(); } } } }
以上代码的解释:
- 在页面中使用
mounted
钩子函数添加backbutton
事件的监听函数; - 在页面关闭时,使用
destroyed
钩子函数来删除backbutton
事件监听函数; - 在
onBackButton
函数中,判断当前是否为 Android 设备; - 如果是 Android 设备,并且历史记录不为0,就调用
$router.go(-1)
返回上一页; - 如果历史记录为0,就调用
navigator.app.exitApp()
直接退出应用。
总结
在 Vue.js SPA 应用中,要经常考虑多种设备、多种浏览器窗口下的运行情况。为了解决 Android 设备下 Back 键失效的问题,我们需要在 Vue Router 中添加额外的逻辑来控制页面的导航与历史记录,并且需要在每个页面中添加 Back 键的点击事件来控制当前页面的退出。掌握如何解决这个问题,可以提高开发者对多种设备属性的掌握能力。
来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/654fafdb7d4982a6eb8a3da2