当前位置: 首页 > news >正文

鸿蒙NEXT Web组件与JavaScript交互:打通原生与前端的桥梁

1. 引言

在鸿蒙应用开发中,Web组件是一个强大的工具,它允许开发者在原生应用中嵌入和展示Web内容。但仅仅展示网页还不够,真正的价值在于原生应用与前端页面之间的双向通信能力。通过Web组件,鸿蒙NEXT应用可以调用前端页面的JavaScript函数,实现数据交换和功能互动,这为混合开发模式开辟了新的可能性。

本文将深入探讨如何在鸿蒙NEXT中使用Web组件与前端JavaScript进行交互,包括基础用法、高级技巧和实际应用场景。

2. Web组件基础

2.1 Web组件简介

Web组件是鸿蒙系统提供的用于显示网页内容的组件,它基于强大的Web渲染引擎,能够高效地加载和显示Web页面。基本使用方法如下:

typescript

import web_webview from '@ohos.web.webview';@Entry
@Component
struct WebComponent {webviewController: web_webview.WebviewController = new web_webview.WebviewController();build() {Column() {// 加载在线网页Web({ src: 'https://www.example.com', controller: this.webviewController })// 或加载本地网页// Web({ src: $rawfile('index.html'), controller: this.webviewController })}}
}

2.2 常用属性配置

为了使Web组件更好地与JavaScript交互,需要配置一些重要属性:

typescript

Web({ src: $rawfile('index.html'), controller: this.controller }).javaScriptAccess(true)    // 启用JavaScript执行.fileAccess(true)          // 允许访问本地文件.zoomAccess(true)          // 允许缩放.onPageEnd((e) => {// 页面加载完成回调console.info('页面加载完成');})

3. 应用侧调用前端JavaScript函数

3.1 runJavaScript方法

鸿蒙NEXT提供了runJavaScript()方法,允许应用侧直接调用前端页面中的JavaScript函数。

前端页面代码

html

<!DOCTYPE html>
<html>
<body>
<script>// 无参函数function htmlTest() {console.info('JavaScript Hello World! ');document.getElementById('demo').innerHTML = '内容已更新';}// 有参函数function updateContent(newContent) {document.getElementById('demo').innerHTML = newContent;}
</script><p id="demo">初始内容</p>
</body>
</html>

应用侧调用代码

typescript

import web_webview from '@ohos.web.webview';@Entry
@Component
struct WebComponent {webviewController: web_webview.WebviewController = new web_webview.WebviewController();build() {Column() {Web({ src: $rawfile('index.html'), controller: this.webviewController})Button('调用无参函数').onClick(() => {// 调用无参函数this.webviewController.runJavaScript('htmlTest()');})Button('调用有参函数').onClick(() => {// 调用有参函数this.webviewController.runJavaScript('updateContent("来自鸿蒙应用的内容")');})}}
}

3.2 执行JavaScript代码块

除了调用现有函数,还可以直接执行JavaScript代码块:

typescript

Button('执行代码块').onClick(() => {// 直接执行JavaScript代码this.webviewController.runJavaScript(`document.body.style.backgroundColor = '#f0f0f0'; console.log('背景色已更改');`);})

3.3 处理返回值

runJavaScript方法可以接收前端函数的返回值:

typescript

Button('获取返回值').onClick(() => {this.webviewController.runJavaScript('getData()', (error, result) => {if (error) {console.error(`执行失败: ${error}`);return;}console.info(`收到返回值: ${result}`);// 处理结果});})

4. 前端调用应用侧方法

4.1 注册应用侧对象

为了使前端页面能够调用应用侧的方法,需要将应用侧的对象注册到Web组件中。

方式一:初始化时注册(javaScriptProxy)

typescript

import web_webview from '@ohos.web.webview';// 定义要注册的类
class AppSideObject {test(): string {return 'ArkTS Hello World!';}showMessage(message: string): string {console.info(`收到前端消息: ${message}`);return `已收到: ${message}`;}
}@Entry
@Component
struct WebComponent {webviewController: web_webview.WebviewController = new web_webview.WebviewController();@State appObj: AppSideObject = new AppSideObject();build() {Column() {Web({ src: $rawfile('index.html'), controller: this.webviewController}).javaScriptProxy({object: this.appObj,name: "harmonyApp", // 前端通过此名称访问methodList: ["test", "showMessage"], // 暴露的方法列表controller: this.webviewController})}}
}
方式二:初始化后注册(registerJavaScriptProxy)

typescript

import web_webview from '@ohos.web.webview';
import business_error from '@ohos.base';@Entry
@Component
struct WebComponent {webviewController: web_webview.WebviewController = new web_webview.WebviewController();@State appObj: AppSideObject = new AppSideObject();build() {Column() {Button('注册对象到前端').onClick(() => {try {this.webviewController.registerJavaScriptProxy(this.appObj, "harmonyApp", ["test", "showMessage"]);// 注册后需要刷新才能生效this.webviewController.refresh();} catch (error) {let e: business_error.BusinessError = error as business_error.BusinessError;console.error(`ErrorCode: ${e.code}, Message: ${e.message}`);}})Web({ src: $rawfile('index.html'), controller: this.webviewController })}}
}

4.2 前端调用方法

注册完成后,前端页面可以通过注册的对象名称调用应用侧的方法:

html

<!DOCTYPE html>
<html>
<body>
<button type="button" οnclick="callHarmony()">调用鸿蒙方法</button>
<p id="result"></p><script>function callHarmony() {// 调用应用侧方法let result = harmonyApp.showMessage('你好,鸿蒙!');document.getElementById("result").innerHTML = result;console.info('调用成功: ' + result);}
</script>
</body>
</html>

4.3 复杂数据类型传递

应用侧和前端之间可以传递复杂数据类型,如数组和对象:

typescript

class DataHandler {getComplexData(): Array<Number> {return [1, 2, 3, 4];}processUserData(user: Object): string {console.info(`收到用户数据: ${JSON.stringify(user)}`);return "处理成功";}
}

前端调用:

javascript

// 获取数组数据
let dataArray = harmonyApp.getComplexData();
console.log(dataArray);// 传递对象数据
let user = {name: '张三', age: 25};
let result = harmonyApp.processUserData(user);

5. 建立双向数据通道

除了函数调用,鸿蒙NEXT还提供了更强大的Web消息端口(WebMessagePort)机制,用于建立应用侧和前端页面之间的双向数据通道。

5.1 创建消息端口

typescript

// xxx.ets
import web_webview from '@ohos.web.webview';@Entry
@Component
struct WebComponent {controller: web_webview.WebviewController = new web_webview.WebviewController();ports: web_webview.WebMessagePort[];@State receivedFromHtml: string = '等待接收前端消息';build() {Column() {Text(this.receivedFromHtml).fontSize(20).margin(10)Button('建立数据通道').onClick(() => {// 1. 创建两个消息端口this.ports = this.controller.createWebMessagePorts();// 2. 将一个端口发送到前端页面this.controller.postMessage("__init_port__", [this.ports[0]], "*");// 3. 在另一个端口上监听消息this.ports[1].onMessageEvent((result: web_webview.WebMessage) => {if (typeof result.getData() === 'string') {this.receivedFromHtml = result.getData();}});})Web({ src: $rawfile('index.html'), controller: this.controller })}}
}

5.2 前端页面处理消息端口

html

<!-- index.html -->
<!DOCTYPE html>
<html>
<head><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>WebView Message Port Demo</title>
</head>
<body><h1>WebView Message Port Demo</h1><input id="messageInput" type="text" placeholder="输入要发送的消息"><button οnclick="sendMessage()">发送消息到应用侧</button><p id="receivedMessage">等待接收应用侧消息...</p><script>let remotePort = null;// 监听应用侧发送的消息端口window.addEventListener('message', function(event) {if (event.data === '__init_port__') {remotePort = event.ports[0];// 监听来自应用侧的消息remotePort.onmessage = function(event) {document.getElementById('receivedMessage').innerHTML = event.data;};}});function sendMessage() {if (!remotePort) {console.error('消息端口未初始化');return;}const message = document.getElementById('messageInput').value;remotePort.postMessage(message);}</script>
</body>
</html>

6. 实际应用场景

6.1 身份验证令牌传递

一种常见场景是在原生应用中处理用户认证,然后将令牌传递给前端页面:

typescript

class AuthHandler {getAuthToken(): string {// 从应用侧获取认证令牌return "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...";}
}

前端页面使用:

javascript

// 前端页面获取认证令牌
const token = harmonyApp.getAuthToken();// 使用令牌访问受保护的API
fetch('/api/protected-data', {headers: {'Authorization': `Bearer ${token}`}
});

6.2 原生功能调用

前端页面可以调用设备原生功能,如相机、GPS等:

typescript

class DeviceService {takePicture(): string {// 调用原生相机功能// 返回图片路径或Base64编码return "file://path/to/image.jpg";}getLocation(): Object {// 获取设备位置return {latitude: 39.9042, longitude: 116.4074};}
}

6.3 数据持久化

前端页面可以利用应用侧的数据持久化能力:

typescript

class StorageService {saveData(key: string, value: string): void {// 使用原生存储保存数据Preferences.putSync(key, value);}loadData(key: string): string {// 从原生存储读取数据return Preferences.getSync(key, '');}
}

7. 调试与错误处理

7.1 启用调试模式

在开发过程中,可以启用Web调试功能:

typescript

aboutToAppear() {// 配置Web开启调试模式webview.WebviewController.setWebDebuggingAccess(true);
}

然后可以在Chrome浏览器中通过chrome://inspect检查Web页面。

7.2 错误处理

在JavaScript交互中添加适当的错误处理:

typescript

// 调用JavaScript时的错误处理
this.webviewController.runJavaScript('someFunction()', (error, result) => {if (error) {console.error(`JavaScript执行错误: ${error.code}, ${error.message}`);// 处理错误return;}// 处理成功结果
});// 注册对象时的错误处理
try {this.webviewController.registerJavaScriptProxy(this.appObj, "harmonyApp", ["method1"]);this.webviewController.refresh();
} catch (error) {let e: business_error.BusinessError = error as business_error.BusinessError;console.error(`注册失败: ErrorCode: ${e.code}, Message: ${e.message}`);
}

8. 总结

鸿蒙NEXT的Web组件提供了强大的原生应用与前端JavaScript交互能力,通过本文介绍的几种方式,开发者可以实现:

  1. 应用侧调用前端函数:使用runJavaScript()方法直接调用前端页面中的JavaScript函数

  2. 前端调用应用侧功能:通过javaScriptProxy()registerJavaScriptProxy()注册应用侧对象供前端调用

  3. 建立双向通信通道:使用Web消息端口实现应用侧和前端页面的持续双向通信

这些功能为开发丰富的混合应用提供了坚实基础,结合了原生应用的性能优势和Web开发的灵活性。在实际项目中,开发者可以根据具体需求选择合适的交互方式,打造无缝的用户体验。


文章转载自:

http://SCShqp0R.rrxgx.cn
http://IgOklvIy.rrxgx.cn
http://pKGG9Jur.rrxgx.cn
http://cYD33S9g.rrxgx.cn
http://eOUoGej8.rrxgx.cn
http://9yUSDWfX.rrxgx.cn
http://3d7h2iI8.rrxgx.cn
http://cjevrSMI.rrxgx.cn
http://aKOhtdfb.rrxgx.cn
http://F9BnuU9k.rrxgx.cn
http://Sk6Qm6d8.rrxgx.cn
http://AKaRDJvF.rrxgx.cn
http://qrqoMpqI.rrxgx.cn
http://6P54LYrJ.rrxgx.cn
http://pCoIgOXV.rrxgx.cn
http://3N8Zpc1R.rrxgx.cn
http://sGCM9ngr.rrxgx.cn
http://BiFdj4yM.rrxgx.cn
http://0wScAnhQ.rrxgx.cn
http://8DTBl9Yx.rrxgx.cn
http://ymD1YGvX.rrxgx.cn
http://tyAWsuL0.rrxgx.cn
http://8rQa5w41.rrxgx.cn
http://q03qh6GD.rrxgx.cn
http://EoUpctQ7.rrxgx.cn
http://ElevCElC.rrxgx.cn
http://K5rivuH6.rrxgx.cn
http://hMyVGACA.rrxgx.cn
http://PXmzrFgT.rrxgx.cn
http://46LFMjkJ.rrxgx.cn
http://www.dtcms.com/a/379916.html

相关文章:

  • C#高并发与并行理解处理
  • 终端之外:解锁Linux命令行的魔法与力量
  • wav2vec微调进行疾病语音分类任务
  • 【.Net技术栈梳理】10-.NET Core 程序的执行
  • 【完整源码+数据集+部署教程】仓库物品分类检测图像分割系统源码和数据集:改进yolo11-convnextv2
  • 软件定义汽车(SDV)与区域电子电气架构(Zonal EEA)的技术革新
  • R语言:数据读取与重构、试验设计(RCB/BIB/正交/析因)、ggplot2高级绘图与统计检验(t检验/方差分析/PCA/聚类)
  • ffmpeg切割音频
  • 【论文笔记】RadarOcc: Robust 3D Occupancy Prediction with 4D Imaging Radar
  • 【Axios 教程】从入门到高级
  • 数据库重演Real Application Testing: Database Capture FAQ (Doc ID 1920275.1)
  • 一个海康相机OCR的程序
  • 蚂蚁 S19 Pro+ Hyd 191T:高效能矿机解析与性能评测
  • C++并发编程:std::thread右值形式传参解析
  • 判断子序列
  • 鸿蒙数据安全实战:从 AES 到 RSA 的加密解密全流程解析
  • Python与MiniKanren:逻辑编程的艺术与科学
  • DeviceNet 转 EtherCAT:发那科焊接机器人与倍福 CX5140 在汽车焊装线的高速数据同步通讯配置案例
  • J002 Vue+SpringBoot电影推荐可视化系统|双协同过滤推荐算法评论情感分析spark数据分析|配套文档1.34万字
  • 连续hash函数
  • 七彩喜智慧养老:用科技温暖晚年,让关爱永不掉线
  • C++微基础蓝桥杯之旅9.9-9.12
  • 一款好看的jQuery前端框架-HisUI
  • Go语言io.Copy深度解析:高效数据复制的终极指南
  • k8s-init容器学习
  • 【算法磨剑:用 C++ 思考的艺术・Dijkstra 实战】弱化版 vs 标准版模板,洛谷 P3371/P4779 双题精讲
  • Java大厂面试实录:产业互联网大数据与AI服务场景下的微服务与智能搜索(含详细解读)
  • 苍穹外卖项目笔记day08
  • 智能逗猫球方案MCU控制方案浅析-智能宠物玩具,宠物解闷神器
  • Unity键盘控制角色运动