最近使用 uni-app 开发安卓端的 App,因为要嵌入一个原本已经开发完的系统,打算使用 web-view 的方式进行嵌入。
因为项目工期比较紧,所以是两个前端并行开发,最后再合到一起。
结果就是这个过程中出问题了...
需求
需求方面是:
A同学负责通讯方面的工作,所以页面应该在首页加载的时候就被挂载上去,这样一来启动系统的时候就注册了通讯模块,不影响收发信息。
B同学负责其他部分,在首页展示系统内部的统计数据,可以算是一个安卓端的简易大屏。
原本A同学的方案是在系统页面上创建一个 web-view,然后嵌入系统。这样一来也不影响B同学开发新系统。
问题
结果整合代码的时候才发现,web-view标签 是自动铺满整个页面 的,而且是无法隐藏的。
这就尴尬了,App进来以后直接看到的就是 A同学的通讯页面,无法看到B同学的大屏了。
问题抛到了我手里,我经过一番简单的调研,再加上一顿猛如虎的操作,又通过 Trae 一顿AI,最后回复他们说:无解!

对此 Trae 给出的原因是:uni-app 中内置的 web-view 标签本身没有隐藏的API,在 web-view 标签外增加 view 标签,绑定 v-show 方法不生效。
只能绑定 v-if 生效,但是绑定 v-if=false 的时候相当于 web-view 直接被销毁了,会导致通讯模块收不到信息。
解决
好在天无绝人之路,uni-app 官方文档中表示:在 html5+ 中其实存在 web-view 的 API,能够操作窗口的大小。
那么既然能够操作窗口的大小,肯定也能够控制显隐。
于是乎我使用 Trae 让他使用 html5+ 中的 create 方法创建 web-view,并给出完整的解决方案。
js
createWebView() {
let that = this;
if (this.webviewIns) return;
this.webviewIns = plus.webview.create(
'http://192.168.25.110',
'1008610010' // ID(必须唯一)
{
top: '24px',
bottom: '0px',
width: '300px',
height: '600px',
scrollIndicator: 'none',
scalable: false
}
);
// 设置页面默认隐藏
this.webviewIns.hide();
}
这时候已经成功创建了 web-view 并且处于隐藏状态,不耽误传参。
但是又遇到了一个问题,web-view无法与uni-app通信。
Trae 先给出了 uni-app 官方提供的方法,使用 uni.postMessage 方法,但是在通讯系统中插入了这个方法以后,不报错,并且显示发送消息成功,但uni-app 这边却无法接收到。
Trae 又使用 evalJS 方法插入相应的脚本,但是也没有反应。同样是发送成功,但是接收不到。

两种方案均不可用,我又详细看了看 uni-app 的官方文档,让 Trae 分析 web-view 标签上绑定的 @message 方法应该是经过特殊封装的,能够捕获到 view-view 内使用 uni.postMessage 方法发送的数据。
Trae给出的解释是:由于我现在使用 plus.web-view.create 创建窗口,绕过了uni-app 所以即便是绑定 message 也无效了。

所以采用 html+ 原生方法发送数据,在 web-view 中使用 plus.webview.postMessageToUniNView 方法发送数据。
在 uni-app 端使用 plus.globalEvent.addEventListener 接收数据。
js
// 发送数据
pushMessage() {
plus.webview.postMessageToUniNView({
type: 'tpUniAPP',
args: {
args1: 'test123'
}
}, '__uniapp__service');
}
接收数据方法写在 createWebView 方法内。
js
// 接收数据
createWebView() {
let that = this;
if (this.webviewIns) return;
// 创建一个新的 WebView
this.webviewIns = plus.webview.create(
...
);
// web-view加载完成
this.webviewIns.addEventListener('loaded', () => {
plus.globalEvent.addEventListener('plusMessage', (message)=>{
let data = message?.data?.args?.data;
if(data?.name === 'postMessage') {
if (data?.arg?.type === 'show') {
// 显示
that.webviewIns.show();
}
if (data?.arg?.type === 'hide') {
// 隐藏
that.webviewIns.hide();
}
}
})
});
this.webviewIns.hide();
},
结论
目前主要解决了两个问题:
- web-view 大小、显隐不可控问题。
- web-view 与 uni-app 通信问题。
发送数据方法可以卸载 Pinia 的公共方法中,或者使用 EventBus,统一处理。
Ps: 第二个问题解决方案不是太优雅,如果有兄弟有更好的方案可以分享一下。