NetLab 的网络拓扑画布和 CLI 终端都是用 Web 组件嵌入前端页面实现的。Web 组件让鸿蒙应用能复用成熟的前端生态,是混合开发的关键能力。本文分享 Web 组件加载、rawfile 资源访问、双向通信实战。
一、Web 组件基础
import { webview } from '@kit.ArkWeb';
@Entry
@Component
struct WebPage {
controller: webview.WebviewController = new webview.WebviewController();
build() {
Web({ src: $rawfile('index.html'), controller: this.controller })
.width('100%')
.height('100%')
.javaScriptAccess(true) // 允许JS
.domStorageAccess(true) // 允许localStorage
}
}
二、加载资源方式
2.1 加载本地 rawfile
// 资源放在 entry/src/main/resources/rawfile/ 下
Web({ src: $rawfile('canvas/index.html') })
// 目录结构:
// rawfile/
// canvas/
// index.html
// js/topology.js
// css/style.css
rawfile 资源打包进 HAP,无需网络,离线可用。NetLab 的拓扑画布全部放在 rawfile 下。
2.2 加载远程 URL
Web({ src: 'https://netlab.guidl.top/' })
需配置网络权限 ohos.permission.INTERNET。
2.3 沙箱协议(file:///rawfile://)
// file://protocol 访问应用沙箱文件
Web({ src: 'file://' + getContext().filesDir + '/cache.html' })
三、双向通信(核心)
3.1 ArkTS 调用前端 JS
// ArkTS 侧:通过 controller 执行 JS
this.controller.runJavaScriptCode(`
window.loadTopology('${topologyJson}');
`);
// 前端侧:定义全局方法
window.loadTopology = function(json) {
const topo = JSON.parse(json);
renderTopology(topo);
};
3.2 前端 JS 调用 ArkTS(javaScriptProxy)
// ArkTS 侧:注册代理对象供前端调用
class NativeBridge {
saveTopology(json: string) {
// 保存到鸿蒙本地存储
preferences.put('topology', json);
}
showToast(msg: string) {
promptAction.showToast({ message: msg });
}
}
Web({ src: $rawfile('index.html') })
.javaScriptAccess(true)
.registerJavaScriptProxy({
object: new NativeBridge(),
name: 'nativeBridge', // 前端通过 window.nativeBridge 调用
methodList: ['saveTopology', 'showToast'],
asyncMethodList: [],
isAsync: false
})
// 前端侧:调用原生方法
document.getElementById('save').onclick = () => {
const json = JSON.stringify(getTopology());
window.nativeBridge.saveTopology(json);
window.nativeBridge.showToast('已保存');
};
通信模式:ArkTS→JS 用
runJavaScriptCode 执行前端方法;JS→ArkTS 用 registerJavaScriptProxy 注册代理对象。双向配合实现混合架构交互。四、NetLab 实战案例
NetLab 拓扑画布的完整交互链路:
用户拖拽设备(前端事件)
→ 前端更新画布渲染
→ window.nativeBridge.onTopologyChange(json) // 通知原生
→ ArkTS 保存拓扑到本地存储
→ 触发撤销栈记录
用户点击"加载实验"(ArkTS按钮)
→ controller.runJavaScriptCode('loadExperiment(...)') // 调前端
→ 前端解析JSON渲染拓扑
→ window.nativeBridge.onLoadComplete() // 回调原生
→ ArkTS 更新UI状态
五、踩坑经验
- rawfile 路径:用
$rawfile('path'),不能用字符串拼接到 rawfile 绝对路径 - 代理注册时机:registerJavaScriptProxy 需在 Web 组件 onLoadIntercept 或 onControllerAttached 中注册,太早注册无效
- 前端资源相对路径:rawfile 下的 HTML 引用 JS/CSS 用相对路径,不能用绝对路径
- 跨域限制:远程页面调用 registerJavaScriptProxy 受跨域策略限制,本地 rawfile 无此问题
六、小结
- Web 组件让鸿蒙复用前端生态,适合复杂画布/终端等场景
- rawfile 打包本地资源,离线可用,路径用 $rawfile()
- 双向通信:runJavaScriptCode(ArkTS→JS)+ registerJavaScriptProxy(JS→ArkTS)
- NetLab 拓扑画布 + CLI 终端均用此方案,混合架构成熟可靠