uni-app仿生导航操作WebView(网络页面)

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

所属分类 移动端

相关标签 uni-appWebView导航

需求描述

uni-app的开发实际上本身就是在WebView上开发,只不过很多时候加载的是本地的网页资源。

而在uni-app中嵌入一个网络页面(外部资源),官方也提供了案例就是vue页面中在创建一个web-view标签。

<template>
    <view>
        <web-view src="http://www.mebugs.com/"></web-view>
    </view>
</template>

加载一个网络页面需要解决一个比较尴尬的问题就是网页中做的导航和原生导航共存的问题。

对于APP而言,我们希望尽量使用原生导航,所以在实现中往往隐藏网页自带的导航,然后通过原生导航操作页面。

于是会发现一个问题,原生导航的返回往往是返回到上一个页面(这里指的是uni-app工程里面的上一页)。

解决方案

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

优点:

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

缺点:

  • 需要远端页面修改代码配合
  • 性能不好(疯狂开WebView性能当然不好)
  • 某些场景会不兼容,无限WebView类似于在浏览器上不断打开新Tab页,某些需要记录上一页或来源reffer的场景无法兼容
  1. 网络页面加载器(加载器就一个web-view组件,src属性可由外部传入)
  2. 获取当前页面的子WebView(实际加载网络页面的WebView)对象
  3. 监听子WebView对象并创建计数器
  4. 子WebView对象加载新页面是更新计数器
  5. 触发原生返回按钮时根据计数器判断执行子WebView回退还是页面navigateBack
<template>
    <view>
        <web-view src="http://www.mebugs.com/"></web-view>
    </view>
</template>

<script>
    export default {
        onNavigationBarButtonTap(e) {
            var index = e.index;
            if(index == 0) {
                // 如果计数器>1 执行自WebView回退
                if(this.index > 1) {
                    this.back()
                }else{
                    // 框架回退
                    uni.navigateBack()  
                }
            }
            // 个人中心
            if(index == 1)
            uni.navigateTo({
                url: '/pages/index/mine'
            })
        },
        data() {
            return {
                currentWebview: false,
                view: false,
                index: 0
            }
        },
        onReady() { 
            this.initWebview()
        },
        methods: {
            initWebview() { //初始化并获取子WebView
                // #ifdef APP-PLUS
                this.currentWebview = this.$scope.$getAppWebview() 
                let this_ = this
                // 避免初始化失败 延时判断
                setTimeout(function() {
                    this_.view = this_.currentWebview.children()[0]
                    if(this_.view) {
                        // 子WebView绑定打开新页面触发的事件方法
                        this_.view.onloading = this_.loadNewUrl()
                    }else{
                        // 如果子WebView还是没有 递归获取
                        this_.initWebview()
                    }
                }, 1000)
                // #endif
            },
            back() {
                // 子webView回退
                this.view.back()
                this.index = this.index - 1
            },
            loadNewUrl() {
                // 计数器增加
                this.index = this.index + 1
            }
        }
    }
</script>

实现效果

/static/upload/post/1645527176903.jpg

米虫

做一个有理想的米虫,伪全栈程序猿,乐观主义者,坚信一切都是最好的安排!

本站由个人原创、收集或整理,如涉及侵权请联系删除

本站内容支持转发,希望贵方携带转载信息和原文链接

本站具有时效性,不提供有效、可用和准确等相关保证

本站不提供免费技术支持,暂不推荐您使用案例商业化

选择个人头像

昵称

邮箱

QQ

网址

评论提示

  • 头像:系统为您提供了12个头像自由选择,初次打开随机为你选择一个
  • 邮箱:可选提交邮箱,该信息不会外泄,或将上线管理员回复邮件通知
  • 网址:可选提交网址,评论区该地址将以外链的形式展示在您的昵称上
  • 记忆:浏览器将记忆您已选择或填写过得信息,下次评论无需重复输入
  • 审核:提供一个和谐友善的评论环境,本站所有评论需要经过人工审核