HarmonyOS鸿蒙Next中如何实现 ArkWeb 与原生双向 JS 交互?
HarmonyOS鸿蒙Next中如何实现 ArkWeb 与原生双向 JS 交互?
问题描述
使用 ArkWeb 组件加载网页后,需要让网页 JS 调用鸿蒙原生方法(如获取设备信息),同时鸿蒙原生也需调用网页 JS 函数(如传递用户数据),尝试用webviewController的方法但调用失败,如何实现稳定的双向交互?关键字:ArkWeb、JS 交互、双向通信、webviewController、鸿蒙原生
回答内容
原理解析
ArkWeb 的 JS 交互基于 “原生注入 API + 网页暴露全局函数” 的机制:
- 原生→JS:通过
webviewController.executeScript()调用网页全局 JS 函数; - JS→原生:通过
webview.setWebMessageListener()监听网页消息,或注入原生 API 供 JS 调用,核心是确保双方通信通道初始化完成后再交互,避免时机过早导致失败。
实现步骤
步骤 1:鸿蒙原生注入 API,供网页 JS 调用
import { webview } from '@kit.ArkWeb';
import common from '@ohos.app.ability.common';
@Entry
@Component
struct ArkWebJSInteraction {
controller: webview.WebviewController = new webview.WebviewController();
context = getContext(this) as common.UIAbilityContext;
build() {
Column() {
Web({
src: $rawfile('test.html'), // 本地网页,也可是远程URL
controller: this.controller
})
.onPageEnd(() => {
// 网页加载完成后,注入原生API到JS环境
this.injectNativeApi();
})
.webMessageListener((message) => {
// 监听JS发送的消息(第二种交互方式)
console.log('JS发送的消息:', message);
// 回复JS
this.controller.postMessageToWeb({ type: 'reply', data: '收到消息' });
})
}
}
// 注入原生API供JS调用
injectNativeApi() {
const nativeApi = {
// 原生方法:获取设备型号
getDeviceModel: () => {
return 'HarmonyOS Device'; // 实际可通过系统API获取真实设备信息
},
// 原生方法:打开原生弹窗
showNativeDialog: (title: string, content: string) => {
promptAction.showDialog({ title, message: content });
}
};
// 注入API到JS的window对象下,命名为nativeApi
this.controller.executeScript({
script: `window.nativeApi = ${JSON.stringify(nativeApi)};`
}).then(() => {
console.log('原生API注入成功');
}).catch((err) => {
console.error('注入失败:', err);
});
}
}
步骤 2:网页 JS 调用原生 API + 暴露函数供原生调用
创建src/main/resources/rawfile/test.html:
<!DOCTYPE html>
<html>
<body>
<button onclick="callNativeApi()">调用原生方法</button>
<script>
// 1. JS调用鸿蒙原生注入的API
function callNativeApi() {
// 调用原生的getDeviceModel方法
const model = window.nativeApi.getDeviceModel();
alert('设备型号:' + model);
// 调用原生的弹窗方法
window.nativeApi.showNativeDialog('JS调用', '这是JS触发的原生弹窗');
// 向原生发送消息(通过webMessageListener监听)
window.harmony.postMessage({ type: 'request', data: '需要用户信息' });
}
// 2. 暴露全局函数,供鸿蒙原生调用
window.jsFunction = function(data) {
alert('原生调用JS函数,参数:' + JSON.stringify(data));
return 'JS函数执行成功'; // 可返回结果给原生
};
</script>
</body>
</html>
步骤 3:鸿蒙原生调用网页 JS 函数
// 在需要调用的时机(如按钮点击)执行
callJsFunction() {
// 调用网页的全局函数jsFunction,并传递参数
this.controller.executeScript({
script: `window.jsFunction({ name: '鸿蒙', type: 'native' })`
}).then((result) => {
console.log('JS函数返回结果:', result);
}).catch((err) => {
console.error('调用JS失败:', err);
});
}
避坑提醒
- 必须在
onPageEnd(网页加载完成)后注入 API / 调用 JS,否则window对象未初始化; - 注入的原生方法仅支持序列化数据(JSON 可解析类型),不能传递复杂对象;
- 远程网页需确保
src是 HTTPS 协议(或配置网络安全策略允许 HTTP),否则可能被拦截; - 若调用失败,检查是否开启了
incognitoMode(隐私模式下部分交互可能受限)。
更多关于HarmonyOS鸿蒙Next中如何实现 ArkWeb 与原生双向 JS 交互?的实战教程也可以访问 https://www.itying.com/category-93-b0.html
在HarmonyOS Next中,ArkWeb与原生双向JS交互主要通过WebMessagePort和WebMessage实现。在ArkTS侧,通过WebController获取WebMessagePort对象,使用postMessage()发送消息到Web侧。在Web侧,通过window.ohWebMessage接收并处理消息,也可通过postMessage()回传数据。ArkTS侧通过onMessageEvent()监听并接收Web侧消息。
更多关于HarmonyOS鸿蒙Next中如何实现 ArkWeb 与原生双向 JS 交互?的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
在HarmonyOS Next中,ArkWeb与原生实现双向JS交互的核心是正确使用webviewController的注入和通信机制。您提供的方案基本正确,但需要注意几个关键点:
-
JS调用原生:通过
webviewController.executeScript()注入window.nativeApi对象是标准做法。但需确保注入时机在onPageEnd之后,避免网页未加载完成。 -
原生调用JS:使用
executeScript()调用全局函数window.jsFunction()可行,但要注意参数传递需为JSON可序列化数据。 -
双向通信补充:除了注入API,还可以使用
webMessageListener进行消息通信。网页端通过window.harmony.postMessage()发送,原生端通过webMessageListener接收并可用postMessageToWeb()回复。
常见问题排查:
- 确保
controller实例一致,避免多个controller混用。 - 远程网页需处理跨域限制,本地网页路径需正确。
- 注入的API方法需返回Promise或同步可序列化值,不支持回调函数参数。
您提供的代码示例已覆盖主要场景,注意executeScript的script字符串中变量替换需谨慎,避免注入漏洞。实际设备信息获取应使用@ohos.deviceInfo等系统API。

