uni-app原生导航栏操作WebView(网络页面)与返回

页面中的WebView嵌入一个网络页面后,顶部原生导航栏默认是整个页面返回,而实际上我们需要操作的是WebView内网页的后退,因此我们可以通过获取子WebView对象进行操作

uni-app原生导航栏操作WebView(网络页面)与返回

所属分类: APP
专题标签: uni-app 原生 导航栏

需求描述

uni-app的开发实际上本身就是在WebView上开发,只不过很多时候加载的是本地的网页资源。
而在uni-app中嵌入一个网络页面(外部资源),官方也提供了案例就是vue页面中在创建一个web-view标签。

  1. <template>
  2. <view>
  3. <web-view src="http://www.mebugs.com/"></web-view>
  4. </view>
  5. </template>

加载一个网络页面需要解决一个比较尴尬的问题就是网页中做的导航和原生导航共存的问题。
对于APP而言,我们希望尽量使用原生导航,所以在实现中往往隐藏网页自带的导航,然后通过原生导航操作页面。
于是会发现一个问题,原生导航的返回往往是返回到上一个页面(这里指的是uni-app工程里面的上一页)。

解决方案

无限WebView

  1. 创建一个公共的网络页面加载器(加载器就一个web-view组件,src属性需由外部传入)
  2. 网络页面识别当前访问者是APP时,触发新页面访问需要向父组件发送消息(消息内容为新URL),并阻断原生事件
  3. uni-app(加载器)监听消息,再次向加载器发起新的navigate跳转请求,携带新的消息中URL
  4. 触发跳转后的原生导航就是常规的返回

优点:

  • 几乎与原生完全一致的体验
  • 前进后退的路由栈完全一致不会出错

缺点:

  • 需要远端页面修改代码配合
  • 性能不好(疯狂开WebView性能当然不好)
  • 某些场景会不兼容,无限WebView类似于在浏览器上不断打开新Tab页,某些需要记录上一页或来源reffer的场景无法兼容

获取webView对象处理

  1. 网络页面加载器(加载器就一个web-view组件,src属性可由外部传入)
  2. 获取当前页面的子WebView(实际加载网络页面的WebView)对象
  3. 监听子WebView对象并创建计数器
  4. 子WebView对象加载新页面是更新计数器
  5. 触发原生返回按钮时根据计数器判断执行子WebView回退还是页面navigateBack
  1. <template>
  2. <view>
  3. <web-view src="http://www.mebugs.com/"></web-view>
  4. </view>
  5. </template>
  6. <script>
  7. export default {
  8. onNavigationBarButtonTap(e) {
  9. var index = e.index;
  10. if(index == 0) {
  11. // 如果计数器>1 执行自WebView回退
  12. if(this.index > 1) {
  13. this.back()
  14. }else{
  15. // 框架回退
  16. uni.navigateBack()
  17. }
  18. }
  19. // 个人中心
  20. if(index == 1)
  21. uni.navigateTo({
  22. url: '/pages/index/mine'
  23. })
  24. },
  25. data() {
  26. return {
  27. currentWebview: false,
  28. view: false,
  29. index: 0
  30. }
  31. },
  32. onReady() {
  33. this.initWebview()
  34. },
  35. methods: {
  36. initWebview() { //初始化并获取子WebView
  37. // #ifdef APP-PLUS
  38. this.currentWebview = this.$scope.$getAppWebview()
  39. let this_ = this
  40. // 避免初始化失败 延时判断
  41. setTimeout(function() {
  42. this_.view = this_.currentWebview.children()[0]
  43. if(this_.view) {
  44. // 子WebView绑定打开新页面触发的事件方法
  45. this_.view.onloading = this_.loadNewUrl()
  46. }else{
  47. // 如果子WebView还是没有 递归获取
  48. this_.initWebview()
  49. }
  50. }, 1000)
  51. // #endif
  52. },
  53. back() {
  54. // 子webView回退
  55. this.view.back()
  56. this.index = this.index - 1
  57. },
  58. loadNewUrl() {
  59. // 计数器增加
  60. this.index = this.index + 1
  61. }
  62. }
  63. }
  64. </script>

实现效果