使用plus.webview.create创建新窗体在打开tabbar页面的时候会闪退

使用plus.webview.create创建新窗体在打开tabbar页面的时候会闪退

开发环境 版本号 项目创建方式
Windows windows11 HBuilderX
产品分类:uniapp/App

PC开发环境操作系统:Windows

PC开发环境操作系统版本号:windows11

HBuilderX类型:正式

HBuilderX版本号:4.87

手机系统:Android

手机系统版本号:Android 12

手机厂商:模拟器

手机机型:oppo

页面类型:vue

vue版本:vue2

打包方式:云端

项目创建方式:HBuilderX

示例代码:

```html
<template>  
    <!-- <web-view :src="payLink">  

    </web-view> -->  
</template>  

<script>  
    import common from '@/common/common.js';  

    export default {  
        data() {  
            return {  
                proxyUrl: '',  
                payLink: '',  
                orderNum: '',  
                checkInterval: null,  
                paymentCompleted: false,  
                wv:null,  
                tt:null  
            }  
        },  
        onLoad(options) {  
            console.log('支付页面参数:', options)  

            if(options && options.data){  
                const data = JSON.parse(options.data);  
                this.payLink = data.payLink || '';  
                this.orderNum = data.orderNum || '';  
                // 提取订单号  
                this.extractOrderNum();  
                    try{  
                        if(plus){  
                            setTimeout(() => {  
                                var w=plus.nativeUI.showWaiting();  

                               this.wv = plus.webview.create(  
                                data.payLink,  
                                'myWebview2',  
                                {  
                                    top: '80px',  
                                    bottom: '0px',  
                                    width: '100%',  
                                    height: '100%',  
                                    zindex: 100,   
                                }  
                               );  
                               this.wv.show('none', 0);  
                               this._isActive = true;  
                               const self = this;  

                               this.wv.addEventListener('loaded', function(){  
                                    w.close();  
                                    w=null;  
                                }, false);  

                               this.wv.addEventListener('error', function(e) {  
                                           w.close();  
                                           uni.showModal({  
                                               title: '加载失败',  
                                               content: '请检查网络或链接地址',  
                                               showCancel: false  
                                           });  
                                }, false);     
                                this.wv.addEventListener('close', (e) => {  
                                        uni.switchTab({  
                                            url:'/pages/user/user',  
                                            success(res){  
                                                uni.showToast({  
                                                    title: "跳转成功",  
                                                    icon: 'none'  
                                                });  
                                            },  
                                            fail(err){  
                                                uni.showToast({  
                                                    title: JSON.stringify(err),  
                                                    icon: 'none',  
                                                    duration:10000  
                                                });  
                                            }  
                                        });  
                                     // uni.showToast({  
                                     //     title: 'Webview ID:'+this.wv.id +'已销毁',  
                                     //     icon: 'none'  
                                     // });  
                                     this.wv = null;  

                                 }, false);  
                        }, 300); // 100ms 延迟  
                        }  
                    }catch(error){  
                        // uni.showModal({  
                        //  title: 'error',  
                        //  content: JSON.stringify(error),  
                        //  showCancel: false,  
                        //  success: (res) => {  

                        //  }  
                        // });  
                    }  
            }  

        },  
        onBackPress() {  
            plus.webview.close('myWebview2', 'none');  
            return false;  
        },  

        methods: {  
            // 提取订单号  
            extractOrderNum() {  

            },  

        },  
        mounted() {  
            common.setTopLeftBtn(this);  
        }  
    }  
</script>  

操作步骤: 从tabbar页面 pages/user/user 到 pages/userCenter/order 再到 pages/checkout/pay 页面中创建plus.webview.create,再回退到tabbar页面 pages/user/user时App闪退。

预期结果: 正常回到tabbar页面

实际结果: app闪退

bug描述: 使用plus.webview.create创建新窗体,在打开tabbar页面的时候会闪退


3 回复

该bug反馈内容基本完整但存在关键缺失:BUG描述未说明具体触发场景(如从哪个页面跳转tabbar时闪退),缺少崩溃日志;代码示例中混用了小程序API(this.$mp.page.$getAppWebview())和App API,在App环境中不应使用$mp对象,且未处理webview与tabbar页面的层级关系;复现步骤过于笼统(“随便找个页面”),无法精准复现;分类信息中HBuilderX 4.87版本较旧(当前最新版更高),可能已修复此问题。
经分析,该问题不完全是bug:首先,用户错误地在App环境使用小程序专属API $mp,正确做法应通过plus.webview.currentWebview()获取当前webview;其次,根据页面跳转规则,tabbar页面必须用switchTab跳转,但webview关闭后直接调用uni.switchTab可能因页面栈异常导致闪退,尤其在旧版本中。建议:1. 升级HBuilderX至最新版;2. 移除$mp相关代码,改用plus.webview.currentWebview().append(this.wv);3. 在webview的close事件中增加延迟或检查当前页面栈状态再跳转;4. 参考webview通信文档规范使用。该问题更可能是API误用而非底层bug,旧版本兼容性不足加剧了现象。 内容为 AI 生成,仅供参考


apk压缩包上传附件上传不了啊,提示压缩包太大了

根据你提供的代码和问题描述,这是一个典型的 Webview 与 TabBar 页面交互导致的闪退问题。主要原因是在 Webview 的 close 事件中使用了 uni.switchTab 跳转 TabBar 页面,这会造成页面栈管理冲突。

问题分析:

  1. 事件监听器作用域问题:在 close 事件监听器中使用了 this.wv = null,但这里的 this 指向的是 Webview 对象而非 Vue 组件实例,可能导致后续操作异常。
  2. TabBar 页面跳转时机不当:在 Webview 关闭事件中直接跳转 TabBar 页面,可能与页面销毁流程产生冲突。
  3. Webview 生命周期管理:可能存在 Webview 未完全销毁时就开始页面跳转的情况。

解决方案:

修改 close 事件监听器的实现方式:

// 在onLoad中修改close事件监听
const self = this;
this.wv.addEventListener('close', function(e) {
    // 使用setTimeout确保在下一个事件循环中执行
    setTimeout(() => {
        // 先确保webview完全销毁
        if (self.wv) {
            plus.webview.close(self.wv.id);
            self.wv = null;
        }
        
        // 使用reLaunch或redirectTo代替switchTab
        uni.reLaunch({
            url: '/pages/user/user',
            success: function() {
                console.log('跳转到TabBar页面成功');
            },
            fail: function(err) {
                console.error('跳转失败:', err);
            }
        });
    }, 100);
}, false);

关键修改点:

  1. 使用箭头函数或保存this引用:确保在事件回调中能正确访问Vue实例
  2. 添加延迟执行:使用 setTimeout 确保Webview完全关闭后再执行跳转
  3. 使用reLaunch代替switchTabreLaunch 会关闭所有页面并打开新页面,避免页面栈冲突
  4. 显式关闭Webview:在跳转前确保Webview被正确关闭

替代方案: 如果仍需使用 switchTab,可以尝试在页面 onHideonUnload 生命周期中处理Webview的销毁:

onUnload() {
    if (this.wv) {
        plus.webview.close(this.wv.id);
        this.wv = null;
    }
}
回到顶部