《HarmonyOSNext Web组件双向通信开发指南:JavaScript互调+动态注册+跨端数据流转实战》
2025-06-14 13:30:59
112次阅读
0个评论
《HarmonyOSNext Web组件双向通信开发指南:JavaScript互调+动态注册+跨端数据流转实战》
##Harmony OS Next ##Ark Ts ##教育
本文适用于教育科普行业进行学习,有错误之处请指出我会修改。
🚀 一、应用侧如何调用前端JS函数?
应用侧有两种神器可以调用前端页面的JavaScript函数:runJavaScript()
和它的升级版 runJavaScriptExt()
!两者的核心区别是:
runJavaScript()
:只能传字符串类型的脚本runJavaScriptExt()
:更强更灵活!支持字符串和二进制数据(ArrayBuffer),还能用AsyncCallback异步获取结果!
📌 举个栗子:点击应用按钮让前端字体变绿! 当我们在应用侧点击"runJavaScript"按钮时,触发前端页面的
htmlTest()
方法:
💻 前端页面代码
<!-- index.html -->
<!DOCTYPE html>
<html>
<body>
<button type="button" onclick="callArkTS()">点我变魔术!</button>
<h1 id="text">原始黑色文字👉调用runJavaScript变绿🍀,runJavaScriptCodePassed变红🔥</h1>
<script>
// 有参函数调用
var param = "从ArkTS发来的消息:Hi JS!";
function htmlTest(param) {
document.getElementById('text').style.color = 'green';
console.log(param); // 控制台打印参数
}
// 无参函数调用(和上面是同一个函数名演示不同场景)
function htmlTest() {
document.getElementById('text').style.color = 'green';
}
// 按钮触发桥接函数
function callArkTS() {
changeColor();
}
</script>
</body>
</html>
⚙️ 应用侧ArkTS代码
// WebComponent.ets
import { webview } from '@kit.ArkWeb';
@Entry
@Component
struct WebComponent {
controller: webview.WebviewController = new webview.WebviewController();
aboutToAppear() {
// 开启Web调试模式(重要!)
webview.WebviewController.setWebDebuggingAccess(true);
}
build() {
Column() {
Button('runJavaScript')
.onClick(() => {
// 调用无参版:去掉param
this.controller.runJavaScript('htmlTest()');
})
Button('runJavaScriptCodePassed')
.onClick(() => {
// 直接注入JS代码片段
this.controller.runJavaScript(
`function changeColor(){
document.getElementById('text').style.color = 'red'
}`
);
})
// 加载本地HTML页面
Web({
src: $rawfile('index.html'),
controller: this.controller
})
}
}
}
🔌 二、注册应用侧方法到前端
想让前端页面调用应用侧的方法?我们需要把ArkTS方法"注入"到前端!有两种神操作:
方式1:初始化时注册(超省心!)
// 初始化注册版.ets
import { webview } from '@kit.ArkWeb';
// 要注册的测试类
class TestAgent {
test(): string {
return 'ArkTS发来的问候!';
}
}
@Entry
@Component
struct WebComponent {
controller: webview.WebviewController = new webview.WebviewController();
@State agent: TestAgent = new TestAgent(); // 注册对象
build() {
Column() {
Button('卸载代理')
.onClick(() => {
this.controller.deleteJavaScriptRegister("agentName");
})
Web({ src: $rawfile('index.html'), controller: this.controller })
// 核心注入操作!
.javaScriptProxy({
object: this.agent,
name: "agentName", // 前端通过该名称调用
methodList: ["test"], // 暴露的方法
controller: this.controller
})
}
}
}
方式2:动态注册(灵活但需手动刷新)
// 动态注册版.ets
import { webview } from '@kit.ArkWeb';
class DynamicAgent {
greet(): string {
return "ArkUI动态注册示例";
}
}
@Entry
@Component
struct Index {
controller: webview.WebviewController = new webview.WebviewController();
@State agent: DynamicAgent = new DynamicAgent();
build() {
Column() {
Button('刷新页面')
.onClick(() => {
this.controller.refresh(); // 注册后必须刷新生效!
})
Button('注册到前端')
.onClick(() => {
// 动态注册关键操作
this.controller.registerJavaScriptProxy(
this.agent,
"dynamicAgent",
["greet"] // 暴露的方法名
);
})
Web({ src: $rawfile('index.html'), controller: this.controller })
}
}
}
⚡ 重要提示:动态注册后必须执行.refresh() 才能生效!
🧩 三、参数传递实战宝典
场景1:传递数组对象
// ArkTS侧
class ArrayAgent {
getNumbers(): number[] {
return [1, 3, 5, 7];
}
}
<!-- 前端调用 -->
<script>
function getData() {
const nums = testAgent.getNumbers();
console.log("收到数组:", nums); // [1,3,5,7]
}
</script>
场景2:传递自定义对象
// 定义学生对象
class Student {
name: string = '';
age: number = 0;
}
class StudentAgent {
getStudent(): Student {
return { name: "小明", age: 18 };
}
}
<script>
function showStudent() {
const stu = studentAgent.getStudent();
alert(`姓名:${stu.name},年龄:${stu.age}`);
}
</script>
场景3:双向回调神操作
// ArkTS接收JS回调
class CallbackAgent {
handle(callback: (data:string) => void) {
setTimeout(() => callback("操作完成!"), 1000);
}
}
<script>
testAgent.handle((result) => {
console.log("回调结果:", result);
});
</script>
🔄 四、Promise异步交互
方式1:ArkTS返回Promise
class PromiseAgent {
fetchData(): Promise<string> {
return new Promise((resolve) => {
setTimeout(() => resolve("获取成功"), 1500);
});
}
}
<script>
promiseAgent.fetchData()
.then(data => console.log(data))
.catch(err => console.error(err));
</script>
方式2:前端生成Promise
<script>
function asyncOperation() {
return new Promise((resolve) => {
testAgent.delayCallback(resolve);
});
}
asyncOperation().then(() => {
console.log("异步操作完成!");
});
</script>
📊 避坑指南总结表
场景 | 易错点 | 解决方案 |
---|---|---|
方法注册未生效 | 忘记调用.refresh() | ✅ 注册后立即刷新页面 |
参数传递失败 | 类型不匹配 | ✅ 用基础类型或JSON对象 |
Promise未执行 | 未正确处理异常 | ✅ 添加.catch()捕获错误 |
内存泄漏 | 未注销注册对象 | ✅ 页面关闭时deleteJavaScriptRegister |
权限校验失败 | permission配置错误 | ✅ 参考官方JSON模板 |
💡 终极提示:调试时务必开启
setWebDebuggingAccess(true)
,配合Chrome DevTools实时查看控制台输出!
🎯 关键要点总结
- 双向通信三剑客
runJavaScript()
➡️ 基础调用javaScriptProxy()
➡️ 初始化注册registerJavaScriptProxy()
➡️ 动态注册(记得refresh!) - 数据传输四原则 ✅ 基础类型直接传 ✅ 对象用Class封装 ✅ 数组自动序列化 ✅ 函数通过回调传递
- 异步交互双通道
Promise方案
:适合明确操作结果的场景Callback方案
:适合事件驱动型交互
最后放个彩蛋🥚:遇到permission
配置头秃时,直接用官方提供的JSON模板改参数值就好啦!不需要自己造轮子~
00
- 0回答
- 0粉丝
- 0关注
相关话题
- 【HarmonyOS 5】鸿蒙Web组件和内嵌网页双向通信DEMO示例
- 《HarmonyOSNext超全开发指南:UIAbility组件与跨端协作完全解析》
- HarmonyOSNext列表开发指南
- OpenHarmony跨平台框架开发指南
- ArkUI-X在Android平台动态化开发指南
- HarmonyOS NEXT跨多个组件之间如何进行数据通信?
- HarmonyNext端侧机器学习与异构计算开发指南
- 【HarmonyOS NEXT】Web 组件的基础用法以及 H5 侧与原生侧的双向数据通讯
- 《HarmonyOSNext全链路通知开发指南:从基础通知到智能跳转的超详细实战》
- 14 HarmonyOS NEXT UVList组件开发指南(一)
- 15 HarmonyOS NEXT UVList组件开发指南(二)
- 16 HarmonyOS NEXT UVList组件开发指南(三)
- 17 HarmonyOS NEXT UVList组件开发指南(四)
- 18 HarmonyOS NEXT UVList组件开发指南(五)
- HarmonyNext:鸿蒙系统下的跨设备通信与数据同步技术