在 鸿蒙(HarmonyOS) 和 React Native(RN) 中,Web 与原生(Native)之间的通信机制与 Android/iOS 有显著不同。下面分别说明它们的通信方案,并对比实现方式。
一、鸿蒙(HarmonyOS)中的 Web 与 Native 通信
鸿蒙使用
WebComponent(@ohos:web.webview) 来加载网页,通信主要通过registerJavaScriptProxy和postMessage(Web → Native) +callHandler(Native → JS) 实现。
✅ 1. Native → JS(调用网页方法)
typescript
ts
编辑
1// ArkTS / HarmonyOS
2import web_webview from '@ohos:web.webview';
3
4@Entry
5@Component
6struct WebViewExample {
7 controller: web_webview.WebviewController = new web_webview.WebviewController();
8
9 build() {
10 Column() {
11 Web({ src: 'https://example.com', controller: this.controller })
12 .onPageEnd(() => {
13 // 页面加载完成后,调用 JS 函数
14 this.controller.callHandler('sayHelloFromNative', ['鸿蒙你好!']);
15 })
16 }
17 }
18}
✅ 2. JS → Native(网页调用原生能力)
步骤 1:定义原生对象(需 @Entry 或 @Component 外部)
php
ts
编辑
1class JsCallback {
2 showToast(msg: string): void {
3 // 调用鸿蒙 API,如弹窗
4 console.log('Native received:', msg);
5 // 可调用 promptAction.showToast 等
6 }
7
8 getDeviceInfo(): string {
9 return JSON.stringify({
10 platform: 'HarmonyOS',
11 version: '4.x'
12 });
13 }
14}
步骤 2:注册 JavaScript 代理
javascript
ts
编辑
1Web({ src: 'local.html', controller: this.controller })
2 .registerJavaScriptProxy(new JsCallback(), 'harmonyBridge')
3 .onPageEnd(() => {
4 // 确保代理已注入
5 })
步骤 3:Web 端调用
xml
html
预览
1<!-- local.html -->
2<script>
3 function callNative() {
4 harmonyBridge.showToast('Hello from Web!');
5 const info = harmonyBridge.getDeviceInfo();
6 console.log(info);
7 }
8</script>
9<button onclick="callNative()">Call HarmonyOS</button>
✅ 特点:
- 类似 Android 的
addJavascriptInterface- 方法自动暴露,无需注解
- 支持同步返回值(JS 可直接接收)
二、React Native(RN)中的 Web 与 Native 通信
RN 官方不直接支持 WebView 双向通信,需借助
react-native-webview第三方库(由社区维护,Facebook 官方推荐)。
✅ 1. 安装依赖
bash
bash
编辑
1npm install react-native-webview
2# iOS 需 pod install
✅ 2. JS(React Native) ↔️ Web 通信
方式 A:injectedJavaScript + onMessage(最常用)
ini
tsx
编辑
1import { WebView } from 'react-native-webview';
2
3const MyWeb = () => {
4 const webViewRef = useRef<WebView>(null);
5
6 const onMessage = (event: any) => {
7 const data = JSON.parse(event.nativeEvent.data);
8 if (data.type === 'GET_USER_INFO') {
9 // 返回数据给 Web
10 webViewRef.current?.postMessage(JSON.stringify({
11 type: 'USER_INFO_RESPONSE',
12 payload: { name: 'Alice', id: 123 }
13 }));
14 }
15 };
16
17 const injectedJs = `
18 (function() {
19 window.ReactNativeWebView.postMessage(JSON.stringify({
20 type: 'GET_USER_INFO'
21 }));
22 })();
23 `;
24
25 return (
26 <WebView
27 ref={webViewRef}
28 source={{ uri: 'https://your-web.com' }}
29 onMessage={onMessage}
30 injectedJavaScript={injectedJs}
31 injectedJavaScriptForMainFrameOnly={true}
32 />
33 );
34};
Web 端监听消息:
javascript
js
编辑
1// Web 页面
2window.addEventListener('message', (e) => {
3 const data = JSON.parse(e.data);
4 if (data.type === 'USER_INFO_RESPONSE') {
5 console.log('User:', data.payload);
6 }
7});
8
9// Web 向 RN 发消息
10window.ReactNativeWebView.postMessage(JSON.stringify({
11 type: 'SHARE_CONTENT',
12 content: 'Hello RN!'
13}));
⚠️ 注意:
window.ReactNativeWebView.postMessage是react-native-webview注入的全局对象。
✅ 3. 高级:使用 injectJavaScript 动态调用
csharp
ts
编辑
1// RN 中动态执行 JS
2webViewRef.current?.injectJavaScript(`
3 window.handleNativeCall({ from: 'RN', time: ${Date.now()} });
4 true; // 必须返回值
5`);
三、对比总结
| 平台 | 通信方式 | Web → Native | Native → Web | 是否支持返回值 | 安全性 |
|---|---|---|---|---|---|
| HarmonyOS | registerJavaScriptProxy + callHandler |
bridge.method() |
controller.callHandler() |
✅ 同步返回 | 中(需校验来源) |
| React Native | react-native-webview + postMessage |
window.ReactNativeWebView.postMessage() |
webViewRef.postMessage() 或 injectJavaScript |
❌ 异步(需回调) | 中(可启用 origin 白名单) |
| Android | addJavascriptInterface / postWebMessage |
Android.method() / port.postMessage |
evaluateJavascript / port.postMessage |
✅ / ✅ | 中 / 高 |
| iOS | WKScriptMessageHandler |
webkit.messageHandlers.xxx.postMessage |
evaluateJavaScript |
❌(需手动回调) | 中 |
四、最佳实践建议
🟢 鸿蒙(HarmonyOS)
- 使用
registerJavaScriptProxy暴露最小必要接口 - 在
onPageBegin/onPageEnd中控制通信时机 - 对敏感操作增加权限校验
🟢 React Native
- 始终使用
react-native-webview(不要用旧版WebView) - 启用
originWhitelist={['https://your-domain.com']} - 消息格式统一(如
{ type, payload }) - 避免在
injectedJavaScript中写复杂逻辑
五、未来趋势
- 鸿蒙 :正逐步完善 Web 能力,未来可能支持更标准的
MessageChannel - React Native :社区推动 WebView 新架构,但短期内仍依赖
postMessage