HarmonyOS 鸿蒙Next ArkWeb网页组件如何与JS交互?Web组件开发指南
HarmonyOS 鸿蒙Next ArkWeb网页组件如何与JS交互?Web组件开发指南
- HarmonyOS 5.0,DevEco Studio 5.0
- 需要在应用中嵌入网页,并实现原生与JS的双向通信
- 不清楚如何调用网页中的JS方法
- 希望网页能调用原生的功能
希望了解HarmonyOS ArkWeb组件的使用方法,包括网页加载、JS注入和双向通信
3 回复
1. 基础Web组件使用
import { webview } from '@kit.ArkWeb'
@Entry
@Component
struct WebPage {
@State url: string = 'https://example.com'
@State progress: number = 0
@State isLoading: boolean = true
controller: webview.WebviewController = new webview.WebviewController()
build() {
Column() {
// 加载进度条
if (this.isLoading) {
Progress({ value: this.progress, total: 100 })
.width('100%')
.height(2)
.color('#36e27b')
}
// Web组件
Web({ src: this.url, controller: this.controller })
.width('100%')
.layoutWeight(1)
.onProgressChange((event) => {
if (event) {
this.progress = event.newProgress
this.isLoading = event.newProgress < 100
}
})
.onPageBegin(() => {
this.isLoading = true
})
.onPageEnd(() => {
this.isLoading = false
})
.onErrorReceive((event) => {
console.error('网页加载错误:', event?.error?.getErrorInfo())
})
}
}
}
2. 原生调用JS方法
@Entry
@Component
struct WebJSPage {
controller: webview.WebviewController = new webview.WebviewController()
// 调用网页中的JS方法
callJSFunction(): void {
// 执行JS代码
this.controller.runJavaScript('showAlert("来自原生的消息")')
// 带返回值的调用
this.controller.runJavaScript('getData()')
.then((result) => {
console.info('JS返回值:', result)
})
.catch((err: Error) => {
console.error('JS执行失败:', err)
})
}
// 调用带参数的JS方法
callJSWithParams(name: string, age: number): void {
const script = `updateUserInfo("${name}", ${age})`
this.controller.runJavaScript(script)
}
build() {
Column() {
Row({ space: 12 }) {
Button('调用JS')
.onClick(() => this.callJSFunction())
Button('传递参数')
.onClick(() => this.callJSWithParams('张三', 25))
}
.padding(12)
Web({ src: $rawfile('test.html'), controller: this.controller })
.layoutWeight(1)
}
}
}
3. JS调用原生方法
import { webview } from '@kit.ArkWeb'
@Entry
@Component
struct WebNativePage {
@State message: string = ''
controller: webview.WebviewController = new webview.WebviewController()
aboutToAppear(): void {
// 注册JS可调用的原生方法
webview.WebviewController.setWebDebuggingAccess(true)
}
build() {
Column() {
// 显示来自JS的消息
if (this.message) {
Text(this.message)
.padding(12)
.backgroundColor('#36e27b20')
.borderRadius(8)
.margin(12)
}
Web({ src: $rawfile('callback.html'), controller: this.controller })
.layoutWeight(1)
.javaScriptAccess(true)
.javaScriptProxy({
object: {
// 定义JS可调用的方法
showToast: (msg: string) => {
this.message = msg
console.info('JS调用了showToast:', msg)
},
getUserInfo: () => {
return JSON.stringify({
name: '养鱼达人',
level: 5
})
},
openNativePage: (pageName: string) => {
console.info('打开原生页面:', pageName)
// router.pushUrl({ url: `pages/${pageName}` })
}
},
name: 'NativeBridge', // JS中通过此名称调用
methodList: ['showToast', 'getUserInfo', 'openNativePage'],
controller: this.controller
})
}
}
}
4. HTML文件示例
<!-- resources/rawfile/callback.html -->
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>JS交互测试</title>
<style>
body { padding: 20px; font-family: sans-serif; }
button { padding: 10px 20px; margin: 5px; }
</style>
</head>
<body>
<h2>JS与原生交互测试</h2>
<button onclick="callNativeToast()">调用原生Toast</button>
<button onclick="getNativeUserInfo()">获取用户信息</button>
<button onclick="openPage()">打开原生页面</button>
<div id="result"></div>
<script>
// 调用原生方法显示Toast
function callNativeToast() {
NativeBridge.showToast('Hello from JavaScript!');
}
// 获取原生返回的数据
function getNativeUserInfo() {
const userInfo = NativeBridge.getUserInfo();
document.getElementById('result').innerText = '用户信息: ' + userInfo;
}
// 打开原生页面
function openPage() {
NativeBridge.openNativePage('FishDetail');
}
// 供原生调用的方法
function showAlert(msg) {
alert(msg);
}
function getData() {
return JSON.stringify({ status: 'ok', data: [1, 2, 3] });
}
function updateUserInfo(name, age) {
document.getElementById('result').innerText = `姓名: ${name}, 年龄: ${age}`;
}
</script>
</body>
</html>
5. Web组件常用配置
Web({ src: this.url, controller: this.controller })
.javaScriptAccess(true) // 允许执行JS
.domStorageAccess(true) // 允许DOM存储
.fileAccess(true) // 允许文件访问
.imageAccess(true) // 允许加载图片
.mixedMode(MixedMode.All) // 允许混合内容
.cacheMode(CacheMode.Default) // 缓存模式
.userAgent('CustomUA/1.0') // 自定义UA
.zoomAccess(false) // 禁止缩放
.verticalScrollBarAccess(false) // 隐藏滚动条
6. 常用控制方法
// 刷新页面
this.controller.refresh()
// 后退
if (this.controller.accessBackward()) {
this.controller.backward()
}
// 前进
if (this.controller.accessForward()) {
this.controller.forward()
}
// 停止加载
this.controller.stop()
// 清除缓存
this.controller.removeCache(true)
// 获取当前URL
const currentUrl = this.controller.getUrl()
// 获取标题
const title = this.controller.getTitle()
关键点: javaScriptProxy中的methodList必须包含所有要暴露给JS的方法名
更多关于HarmonyOS 鸿蒙Next ArkWeb网页组件如何与JS交互?Web组件开发指南的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
ArkWeb通过WebMessagePort实现双向通信
在ArkTS侧使用createWebMessagePort()创建端口,通过postWebMessage()发送消息给JS。
JS侧通过message事件监听接收消息,使用postMessage()回传数据。
支持基本数据类型和对象传输。
在HarmonyOS Next中,ArkWeb组件通过@ohos.web.webview提供网页与ArkTS原生应用的双向交互能力。以下是核心实现方法:
1. 网页加载
使用WebController加载网页:
import { webview } from '@ohos.web.webview';
@Entry
@Component
struct WebComponent {
controller: webview.WebviewController = new webview.WebviewController();
build() {
Column() {
// 加载远程或本地网页
Web({ src: 'https://example.com', controller: this.controller })
.onPageEnd(() => {
console.info('页面加载完成');
})
}
}
}
2. 原生调用JS方法
通过runJavaScript执行JS代码并获取返回值:
// 调用无返回值方法
this.controller.runJavaScript('window.jsMethod()');
// 调用有返回值方法
this.controller.runJavaScript('window.getData()', (error, result) => {
if (!error) {
console.info('JS返回值:', result);
}
});
3. JS调用原生方法
步骤1:注册JS桥接对象
// 定义原生对象
class NativeBridge {
static showToast(message: string) {
// 调用原生UI能力
prompt.showToast({ message });
}
}
// 注册到Web
this.controller.registerJavaScriptProxy(
new NativeBridge(), // 桥接对象
'nativeBridge', // JS中对象名
['showToast'] // 暴露的方法列表
);
步骤2:JS中调用原生方法
// 网页JS代码
if (window.nativeBridge) {
window.nativeBridge.showToast('来自网页的消息');
}
4. 双向通信完整示例
// ArkTS侧
@Entry
@Component
struct WebDemo {
controller: webview.WebviewController = new webview.WebviewController();
aboutToAppear() {
// 注册JS可调用的方法
this.controller.registerJavaScriptProxy(
{
sendToNative: (data: string) => {
console.info('收到JS数据:', data);
return 'ArkTS已收到';
}
},
'arkBridge',
['sendToNative']
);
}
callJS() {
// 调用JS方法
this.controller.runJavaScript(`
if (window.receiveFromNative) {
window.receiveFromNative('原生数据');
}
`);
}
build() {
Column() {
Button('调用JS').onClick(() => this.callJS())
Web({
src: $rawfile('index.html'),
controller: this.controller
})
}
}
}
<!-- 网页侧 index.html -->
<script>
// 接收原生调用
window.receiveFromNative = function(data) {
console.log('收到原生数据:', data);
document.getElementById('msg').innerText = data;
};
// 调用原生方法
function callNative() {
if (window.arkBridge) {
const result = window.arkBridge.sendToNative('来自网页的数据');
console.log('原生返回:', result);
}
}
</script>
关键注意事项:
- 使用
registerJavaScriptProxy注册的方法必须是同步的 runJavaScript回调在主线程执行,避免耗时操作- 本地网页资源放在
resources/rawfile目录 - 通过
onConsole可捕获网页console日志
这种设计实现了ArkTS与JavaScript的完全双向通信,支持复杂数据类型的传递。

