Weex WebView 落地指南:从加载 H5 到双向通信的完整流程
Weex WebView 落地指南:从加载 H5 到双向通信的完整流程
【免费下载链接】weexA framework for building Mobile cross-platform UI项目地址: https://gitcode.com/gh_mirrors/we/weex
原生页面已经搭好了,但运营希望活动页用 H5 动态下发,不想每发一次版就改一次 UI。这时你会碰到三个绕不开的问题:H5 怎么嵌进 Weex 页面、加载到哪一步了怎么知道、Weex 和 H5 之间的数据怎么传。weex 框架内置的<web>组件加webview模块就是为这类混合开发准备的,本文按"上屏 → 通信 → 验证"的实际落地顺序,带你把这套 WebView 能力跑通。
🧩 先分清两样东西:<web>组件和webview模块
很多新手第一步就搞混了——模板里写的是组件,JS 里调的是模块,两者在原生侧是分开实现的:
<web>组件:负责渲染和事件。Android 侧是 WXWeb.java,iOS 侧是 WXWebComponent.m,内部各自包了一个系统 WebView(Android 的WebView、iOS 的WKWebView)。webview模块:负责命令式操作(刷新、前进后退、发消息)。Android 对应 WXWebViewModule.java,iOS 对应 WXWebViewModule.m。模块方法在 SDK 初始化时统一注册,注册点在 WXSDKEngine.java 里的registerModule("webview", ...),所以业务侧不用自己注册,weex.requireModule("webview")直接就能拿到。
简单记:模板里挂<web>,JS 里拿webview模块操作这个<web>的 ref。
📄 让 H5 上屏:src、source与四个事件
<web>组件支持两种加载方式:
src:给一个 URL,加载远程页面,运行时动态改src会触发重新加载;source:给一段 HTML 字符串,本地直接渲染;showLoading:是否显示加载进度条(Android 侧还会在进度到 100 时才揭开页面)。
加载过程通过四个事件暴露给 JS,都在标签上声明才会生效:
| 事件 | 时机 | 携带数据 |
|---|---|---|
@pagestart | 开始导航 | url |
@pagefinish | 加载完成 | url、canGoBack、canGoForward(iOS 还带title) |
@error | 加载失败 | Android:type、errorMsg;iOS:errorCode、errorMsg、url |
@receivedtitle | 标题变化(Android) | title |
一段最小可用的写法大概是这样:
<web ref="webview1" :src="url" show-loading @pagestart="onStart" @pagefinish="onFinish" @error="onError"></web>一个容易忽略的细节:原生侧会先检查 JS 是否声明了对应事件(Android 的WXWeb里通过getEvents().contains(...)判断,iOS 的WXWebComponent里通过addEvent:打标记),没声明的事件不会触发,这为后面"为什么收不到 error"埋了伏笔。
📡 双向通信:postMessage 与message事件
这是 Weex WebView 最有价值的部分。两个方向都刻意对齐了 Web 标准的MessageEvent语义,payload 统一是{ type: "message", data: ..., origin: ... }的结构。
Weex → H5:调用webview.postMessage(ref, data)。原生侧拿到 ref 找到组件,然后在页面里执行window.dispatchEvent(new MessageEvent('message', ...)),origin字段自动填当前 bundle 的scheme://host:port。H5 侧就是标准写法:
window.addEventListener("message", (e) => { if (e.origin !== "https://your-bundle-host") return; // 校验来源 console.log(e.data); });H5 → Weex:两个平台的注入方式不同,但对 H5 代码是透明的:
- iOS 在页面启动时注入一段脚本,把
window.postMessage指向webkit.messageHandlers.weex,消息经WKScriptMessageHandler回来后触发组件的message事件; - Android 则在
onPageFinished时改写window.postMessage,走 JSInterface 桥(老系统降级为prompt方案)把数据带回原生。
H5 侧调用postMessage(data, targetOrigin)后,JS 里在<web>标签上监听@message就能拿到{ type, data, origin }。
⚠️ 安全建议:双向都要校验origin。H5 页面上可能被注入的脚本也能调postMessage,Weex 侧收到后建议按来源白名单过滤,别直接拿data去改业务状态。
🧭 导航控制与加载体验
webview模块暴露的命令式方法一共四个,全部以 ref 作为第一个参数:
web.reload(ref):重新加载当前页面;web.goBack(ref)/web.goForward(ref):历史栈前进后退;web.postMessage(ref, data):上一节讲过,这里不再展开。
两个实用技巧:
- 按钮置灰逻辑:
pagefinish事件里的canGoBack/canGoForward正好用来控制返回/前进按钮的可用状态,iOS 侧在真正执行前也会再做一次canGoBack检查,不会越界。 - 标题栏同步:监听
@receivedtitle,把 H5 页面的 title 同步到原生导航栏,用户感知上就是一个"完整网页"。
仓库里的测试页 web-event.vue 把这套交互完整演示了一遍:按钮触发 reload/goBack/goForward,三个事件回调把 url 显示在页面上做断言,可以直接照着抄。
✅ 跑起来验证:两个调试视角
验证混合开发效果,建议同时用两个视角:
- 真机/模拟器跑 demo 工程:iOS 用 playground/ios/ 下的 WeexDemo,Android 用 playground/android/;HarmonyOS 侧可以用 DevEco Studio 直接跑起工程观察日志,类似下面这种运行窗口。
- DevTools 看页面结构:H5 内容出问题时,在浏览器开发者工具里检查 DOM 和事件派发,确认消息有没有真的到达
window。
验证顺序建议:先确认pagestart→ 再确认pagefinish→ 最后测postMessage往返。web-event.vue里故意先配了一个不存在的域名来触发error事件,一秒钟内就能把"错误链路"也验掉。
🩹 踩坑速答
- 收不到
@error?检查标签上是否真的写了@error,没声明的事件原生侧不会派发。 postMessage报组件找不到?第一个参数传的是this.$refs.xxx对应的 ref 字符串,不是组件对象;确认 ref 名字和模板一致。- Android 的 error 信息很粗?原生侧目前只区分
page error/http error/ssl error三类文案;需要精确错误码时看 iOS 侧的errorCode或自行扩展IWebView。 - 还在用
notifyWebview?iOS 源码里已标注将被逐步弃用,新代码统一用postMessage,语义更贴近 Web 标准。
收尾
到这里,Weex 的 WebView 集成就完整了:<web>负责上屏与事件,webview模块负责命令式操作,双向通信统一走message事件加origin校验。后续如果要深入平台适配细节(比如 HarmonyOS 上的 Weex 容器),可以从 ohos/docs/weex鸿蒙化指导文档.md 和 ohos/ 目录继续看。建议把本文的事件表贴在手边,遇到"收不到事件"或"消息没到达"时按表逐项核对,绝大多数问题都能在前两节里找到答案。
【免费下载链接】weexA framework for building Mobile cross-platform UI项目地址: https://gitcode.com/gh_mirrors/we/weex
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考