HarmonyOS - 实现 ArkTS 和 web 页面的数据交互

前言

在现在容器化技术盛行的大背景下,移动端的很多页面逻辑需要借助于 web 页面来进行实现。那么必不可免的就需要进行原生端和 web 端的数据交互。交互类型有以下两种:

  • 原生端发送数据到 web 端;
  • web 端发送数据到原生端;

那么,在鸿蒙的平台,我们如何来实现这两种类型的数据交互呢?让我们一起来看下吧!

原生端发送数据到 web 端

假设我们需要一个 web 页面来展示一个类似于美团外卖点餐页面,那么该页面需要原生端将其设备的经纬度传给 web 页面来进行客户的地址定位。示例代码一共包含两部分:原生端的代码和 web 页面的代码。

原生端示例代码如下:

kotlin 复制代码
import { webview } from '@kit.ArkWeb';

@Entry
@Component
struct Index {
  private controller: webview.WebviewController = new webview.WebviewController();
  private ports: webview.WebMessagePort[] = [];
  private latitude: number = 39.90
  private longitude: number = 114.10

  build() {
    Column() {
      Button("发送经纬度到 Web 页面").onClick(() => {
        if (this.ports && this.ports[0]) {
          this.ports[1].postMessageEvent("经度:" + this.longitude + ";" + "纬度:" + this.latitude);
        }
      })

      Web({ src: $rawfile('index.html'), controller: this.controller })
        .onPageEnd(() => {
          // 1、创建两个消息端口。
          this.ports = this.controller.createWebMessagePorts();
          // // 2、在应用侧的消息端口上注册回调事件。
          this.ports[1].onMessageEvent((result: webview.WebMessage) => { })
          // 3、将另一个消息端口发送到HTML侧,由HTML侧保存并使用。
          this.controller.postMessage('__init_port__', [this.ports[0]], '*');
        })

    }
    .height('100%')
    .width('100%')
  }
}

首先,导入 ArkUI 的 webview 组件用来加载 web 视图。接着创建四个私有变量来存储相应类型的变量。

页面中包含一个 Button 组件用来模拟原生端向 web 发送数据的过程;和 Web 组件用来加载 HTML。

原生端如果发送数据需要以下四步:

  • 调用 createWebMessagePorts() 获取两个端口号(一个用来原生给 web 发数据;一个用来 web 给 原生发数据)。
  • 调用 onMessageEvent() 进行 web 的数据监听。
  • 调用 postMessage() 将函数名和端口数据传递给 web。
  • 调用 postMessageEvent() 将数据发送给 web。

HTML 示例代码如下:

xml 复制代码
<html>
<head>
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>WebView Message Port Demo</title>
</head>
<body>
<h1>外卖列表</h1>
<p class="output">默认经纬度</p>
</body>
<script>
    var h5Port;
    var output = document.querySelector('.output');
    window.addEventListener('message', function (event) {
        if (event.data === '__init_port__') {
            if (event.ports[0] !== null) {
                // 1. 保存从应用侧发送过来的端口。
                h5Port = event.ports[0];
                h5Port.onmessage = function (event) {
                  // 2. 接收ets侧发送过来的消息。
                  var msg = '客户的经纬度:';
                  var result = event.data;
                  if (typeof(result) === 'string') {
                    msg = msg + result;
                  }
                  output.innerHTML = msg;
                }
            }
        }
    })

</script>
</html>

web 要想接收到原生端的数据需要以下两步:

  • 保存原生端发送过来的端口。
  • 通过端口的 onmessage 回调获取到数据并进行展示。

介绍完原生端向 web 端发送数据的流程之后,接下来介绍下如何从 web 端向原生端发送流程。

web 端发送数据到原生端

首先来看下 HTML 中的示例代码:

xml 复制代码
<!--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>外卖列表</h1>
<p class="output">默认经纬度</p>
// 用于模拟发送逻辑
<input type="button" value="SendToEts" onclick="PostMsgToEts('web 消息');"/><br/>
</body>
<script>
    var h5Port;
    var output = document.querySelector('.output');
    window.addEventListener('message', function (event) {
        if (event.data === '__init_port__') {
            if (event.ports[0] !== null) {
                h5Port = event.ports[0];
                h5Port.onmessage = function (event) {
                  var msg = '客户的经纬度:';
                  var result = event.data;
                  if (typeof(result) === 'string') {
                    msg = msg + result;
                  }
                  output.innerHTML = msg;
                }
            }
        }
    })
    // 添加函数通过 h5Port 发送数据
    function PostMsgToEts(data) {
        if (h5Port) {
          h5Port.postMessage(data);
        } else {
          console.error('h5Port is null, Please initialize first');
        }
    }
</script>
</html>

web 端的代码需要添加以下两个步骤:

  • 添加一个标签用来模拟触发发送数据的逻辑。
  • 在 script 标签中添加 PostMsgToEts() 函数用来给原生端发送数据。

原生端的示例代码:

kotlin 复制代码
import { webview } from '@kit.ArkWeb';

@Entry
@Component
struct Index {
  private controller: webview.WebviewController = new webview.WebviewController();
  private ports: webview.WebMessagePort[] = [];
  private latitude: number = 39.90
  private longitude: number = 114.10
  @State messageFromWeb: string = "Hello"

  build() {
    Column() {
      // 添加 Text 组件用来显示 web 端发送来的数据
      Text(this.messageFromWeb)

      Button("发送经纬度到 Web 页面").onClick(() => {
        if (this.ports && this.ports[0]) {
          this.ports[1].postMessageEvent("经度:" + this.longitude + ";" + "纬度:" + this.latitude);
        }
      })

      Web({ src: $rawfile('index.html'), controller: this.controller })
        .onPageEnd(() => {
          this.ports = this.controller.createWebMessagePorts();
          // 实现回调接口接受数据
          this.ports[1].onMessageEvent((result: webview.WebMessage) => {
            if (typeof (result) === 'string') {
              this.messageFromWeb = result;
            }
          })
          this.controller.postMessage('__init_port__', [this.ports[0]], '*');
        })

    }
    .height('100%')
    .width('100%')
  }
}

原生端也需要下面的两步:

  • 声明组件用来展示 web 传送过来的数据。
  • 实现 onMessageEvent 的回调函数接受 web 传递过来的数据。
相关推荐
zhanshuo2 小时前
ArkUI 玩转水平滑动视图:超全实战教程与项目应用解析
harmonyos·arkui
zhanshuo2 小时前
ArkUI Canvas 实战:快速绘制柱状图图表组件
harmonyos·arkui
zhanshuo17 小时前
手把手教你用 ArkUI 写出高性能分页列表:List + onScroll 实战解析
harmonyos
zhanshuo17 小时前
深入解析 ArkUI 触摸事件机制:从点击到滑动的开发全流程
harmonyos
i仙银1 天前
鸿蒙沙箱浏览器 - SandboxFinder
app·harmonyos
Georgewu1 天前
【HarmonyOS】鸿蒙应用开发中常用的三方库介绍和使用示例
harmonyos
AORO20251 天前
遨游三防平板|国产芯片鸿蒙系统单北斗三防平板,安全高效
5g·安全·电脑·制造·信息与通信·harmonyos
HarmonyOS小助手1 天前
“秒开”时代,HarmonyOS预加载让应用启动快如闪电
harmonyos·鸿蒙·鸿蒙生态
三翼鸟数字化技术团队2 天前
鸿蒙平台运行Lua脚本
lua·harmonyos