蜂医
蜂医
  • 发布:2025-11-03 13:38
  • 更新:2025-11-03 13:38
  • 阅读:369

【鸿蒙征文】使用 uni-app 开发鸿蒙 App,如何实现 H5 网页和 App 互通讯?

分类:鸿蒙Next

导语:打通 Web 与 Native 的“任督二脉”

在使用 uni-app 跨端开发时,我们经常需要在 App 内嵌一个 H5 页面(比如活动页、复杂表单页等)。

在鸿蒙(HarmonyOS)应用中,要让这个内嵌的 Web 页面App 的原生能力(Native)进行顺畅的沟通,就需要一个桥梁

本文将基于 UTS 插件,在鸿蒙平台上搭建起 H5 和 App 之间的双向通信机制,实现数据的传递和方法的互调。

🎯 核心目标:实现双向通信

我们最终要实现的效果是:

  1. App -> H5: App 侧可以调用 H5 页面中的 JavaScript 方法,比如向 H5 传递用户 ID 或登录 Token。
  2. H5 -> App: H5 页面可以调用 App 侧提供的原生方法,比如调用相册、获取地理位置,或本例中的“App 弹出提示”。

一、 App 侧:创建 UTS 插件并封装原生能力

在鸿蒙平台上,我们需要通过 UTS 插件来提供 App 侧供 H5 调用的原生 API。

1. 创建 UTS 插件结构

  • 在 uni-app 项目的 uni_modules 目录下,新建一个 UTS 插件,命名为 web-bridge-ohos
  • 确认插件目录结构如下:
    uni_modules/web-bridge-ohos/  
    ├── app-harmony/  
    │   └── index.uts   
    ├── package.json  
    └── interface.uts  

2. 编写 UTS 原生代码 (index.uts)

我们要实现一个核心类,这个类将作为 H5 和 App 通信的桥梁。在鸿蒙中,内嵌网页控件是 WebComponent。我们需要为它设置一个 WebMessagePort 监听器。

在本例中,我们创建一个名为 WebInteractionModule 的类,它负责处理 H5 发送过来的消息。

// 文件路径:uni_modules/web-bridge-ohos/app-harmony/index.uts  

import web_webview from '@ohos.web.webview';  
import hilog from '@ohos.hilog';  
import UIAbility from '@ohos.app.ability.UIAbility';  

const LOG_TAG: string = 'WebBridge';  

/**  
 * 【核心类】Web 交互模块  
 * 负责在鸿蒙平台上注入 Web 消息处理器  
 */  
export class WebInteractionModule {  
  private webViewComponent: web_webview.WebComponent | null = null;  

  /**  
   * 构造函数:初始化时可传入 WebComponent 实例  
   * @param webComp WebComponent 实例  
   */  
  constructor(webComp: web_webview.WebComponent) {  
    this.webViewComponent = webComp;  
    hilog.info(0x0001, LOG_TAG, `WebInteractionModule 初始化成功.`);  
  }  

  /**  
   * 步骤 1: 启用 H5 与 App 互通能力,设置消息监听器。  
   * @param bridgeName 桥接对象名称,H5 侧将使用此名称调用 App 方法。  
   * @param appHandler App 侧处理 H5 消息的回调函数。  
   */  
  public setupBridge(bridgeName: string, appHandler: (message: string) => void): void {  
    if (!this.webViewComponent) return;  

    // 1. 设置 Web 消息处理回调  
    this.webViewComponent.onWebMessage = (data: string) => {  
      hilog.info(0x0001, LOG_TAG, `收到 H5 消息: ${data}`);  
      // 2. 将收到的消息交给 App 业务层处理  
      appHandler(data);  
    };  

    // 3. 注入鸿蒙内置的消息通道对象(关键步骤)  
    // H5 侧将通过 window.[bridgeName].postMessage('data') 来调用  
    this.webViewComponent.injectWebMessagePort(bridgeName);  

    hilog.info(0x0001, LOG_TAG, `已注入 Web 桥接对象: ${bridgeName}`);  
  }  

  /**  
   * 步骤 2: 从 App 侧调用 H5 页面内的 JavaScript 方法。  
   * @param jsCode 要执行的 JavaScript 代码(如:`window.myH5Method('Hello from App')`)。  
   */  
  public callH5Function(jsCode: string): void {  
    if (this.webViewComponent) {  
      this.webViewComponent.executeJs(jsCode, (result) => {  
        hilog.info(0x0001, LOG_TAG, `执行 H5 JS 代码结果: ${result}`);  
      });  
    }  
  }  
}  

// =======================================================  
// 为了方便 uni-app 调用,我们提供一个 UTS 导出的工厂函数  
// =======================================================  

/**  
 * 导出工厂函数:创建并返回 WebInteractionModule 实例  
 * @param webComp H5 视图的 WebComponent 实例  
 * @returns WebInteractionModule 实例  
 */  
export function createWebBridge(webComp: web_webview.WebComponent): WebInteractionModule {  
  return new WebInteractionModule(webComp);  
}

3. UTS 接口定义 (interface.uts)

为了让上层 Vue/JS 代码能顺利使用这个类,我们需要定义接口:

// 文件路径:uni_modules/web-bridge-ohos/interface.uts  

import web_webview from '@ohos.web.webview';  

/**  
 * WebInteractionModule 类的接口定义  
 * 供 uni-app TypeScript/JavaScript 代码使用  
 */  
export interface WebInteractionModule {  
  /**  
   * 启动 App 和 H5 之间的通信桥接。  
   * @param bridgeName H5 侧调用的对象名 (如:'HarmonyAppBridge')  
   * @param appHandler App 侧接收 H5 消息的回调函数。  
   */  
  setupBridge(bridgeName: string, appHandler: (message: string) => void): void;  

  /**  
   * 从 App 侧调用 H5 页面中的 JavaScript 代码。  
   * @param jsCode 要在 H5 中执行的 JS 字符串。  
   */  
  callH5Function(jsCode: string): void;  
}  

/**  
 * UTS 导出函数接口:创建 Web 桥接模块实例  
 * @param webComp WebComponent 实例  
 * @returns WebInteractionModule 实例  
 */  
export type CreateWebBridge = (webComp: web_webview.WebComponent) => WebInteractionModule;

二、 App 侧:在 uni-app 页面中集成 WebComponent

在 uni-app 页面中,我们需要使用自定义组件的方式,引入鸿蒙平台专有的 web-view 组件,并调用 UTS 插件。

1. 页面逻辑 (pages/index/index.vue)

我们创建一个页面,其中包含一个内嵌的 web-view 组件,并实现 H5 消息处理逻辑。

<template>  
  <view class="container">  
    <text class="title">鸿蒙 Web-Native 互通演示</text>  

    <button @click="sendDataToH5">App 发送数据给 H5</button>  

    <view class="message-box">  
      <text>收到 H5 消息: {{ lastH5Message }}</text>  
    </view>  

    <web-view   
      ref="h5WebView"   
      class="h5-content"   
      :src="h5Url"   
      @onHarmonyWebComponentCreated="onWebCreated"   
    ></web-view>  
  </view>  
</template>  

<script lang="uts">  
  import { WebInteractionModule, createWebBridge } from '@/uni_modules/web-bridge-ohos';  
  import web_webview from '@ohos.web.webview';  

  // 【注意】请替换成你实际 H5 文件的网络地址或本地路径  
  const H5_PAGE_URL: string = 'https://yourdomain.com/path/to/h5/index.html';   
  const BRIDGE_OBJECT_NAME: string = 'HarmonyAppBridge'; // 供 H5 调用的对象名  

  export default {  
    data() {  
      return {  
        h5Url: H5_PAGE_URL,  
        lastH5Message: '暂无消息',  
        webBridge: null as WebInteractionModule | null, // 存储 UTS 桥接模块实例  
        sendCount: 0,  
      }  
    },  
    methods: {  
      /**  
       * 鸿蒙平台 WebComponent 创建成功后触发的事件  
       * @param e 事件对象,包含了 WebComponent 的实例  
       */  
      onWebCreated(e: { component: web_webview.WebComponent }) {  
        console.log('WebComponent 实例已创建');  
        const webComponent = e.component;  

        // 1. 创建 UTS 桥接模块实例  
        this.webBridge = createWebBridge(webComponent);  

        // 2. 设置桥接并注册 App 侧的消息处理器  
        this.webBridge.setupBridge(BRIDGE_OBJECT_NAME, this.handleMessageFromH5);  
      },  

      /**  
       * App 侧处理 H5 页面发送过来的消息  
       * @param message H5 传递过来的 JSON 字符串  
       */  
      handleMessageFromH5(message: string): void {  
        console.log(`App 收到 H5 消息: ${message}`);  
        this.lastH5Message = message;  

        // 示例:App 收到 H5 消息后,可以调用 App 的原生能力,比如 uni.showToast  
        uni.showToast({  
          title: `H5 说: ${message}`,  
          icon: 'none',  
        });  
      },  

      /**  
       * App 侧主动调用 H5 页面中的 JavaScript 方法  
       */  
      sendDataToH5(): void {  
        if (!this.webBridge) {  
          console.error('Web 桥接尚未初始化!');  
          uni.showToast({ title: '桥接未就绪', icon: 'error' });  
          return;  
        }  

        this.sendCount++;  
        const dataToSend = `{"action":"updateUser","userId":1000${this.sendCount}}`;  

        // 构造要执行的 H5 JS 代码  
        // 假设 H5 页面中有一个全局函数名为 `receiveAppMessage`  
        const jsCode: string = `window.receiveAppMessage('${dataToSend}')`;  

        // 调用 UTS 插件方法执行 JS  
        this.webBridge.callH5Function(jsCode);  
      }  
    }  
  }  
</script>  

<style>  
  .container {  
    padding: 20px;  
  }  
  .title {  
    font-size: 18px;  
    font-weight: bold;  
    margin-bottom: 20px;  
    display: block;  
  }  
  .message-box {  
    margin: 15px 0;  
    padding: 10px;  
    border: 1px solid #ddd;  
    background-color: #f0f0f0;  
  }  
  .h5-content {  
    /* 确保 web-view 有足够的高度显示 */  
    width: 100%;  
    height: 300px;   
    margin-top: 20px;  
    border: 1px solid #ccc;  
  }  
</style>

三、 H5 侧:实现双向通信逻辑

H5 页面需要实现两套机制:一套用于接收 App 消息,一套用于发送消息给 App。

1. H5 接收 App 消息的函数

App 侧会调用我们在 H5 中定义的全局函数 window.receiveAppMessage

<script>  
  // 【接收】App -> H5  
  window.receiveAppMessage = function(dataStr) {  
    console.log('H5 收到 App 消息:', dataStr);  
    try {  
      const data = JSON.parse(dataStr);  
      document.getElementById('app-msg').innerText = '最新 App 消息: ' + data.action + ',用户ID:' + data.userId;  
    } catch (e) {  
      document.getElementById('app-msg').innerText = '收到非法消息格式: ' + dataStr;  
    }  
  };  
</script>

2. H5 发送消息给 App 的方法

H5 通过调用 App 侧注入的桥接对象(我们命名为 HarmonyAppBridge)上的 postMessage 方法来发送消息。

<script>  
  // 【发送】H5 -> App  
  function sendToApp(message) {  
    // 检查 App 侧注入的桥接对象是否存在  
    if (window.HarmonyAppBridge && typeof window.HarmonyAppBridge.postMessage === 'function') {  
      window.HarmonyAppBridge.postMessage(message);  
      document.getElementById('h5-status').innerText = '成功发送消息给 App: ' + message;  
    } else {  
      document.getElementById('h5-status').innerText = 'App 桥接对象 (HarmonyAppBridge) 不存在或未就绪!';  
      console.error('App 桥接对象不存在,无法发送消息。');  
    }  
  }  

  // 按钮点击事件示例  
  document.getElementById('send-btn').onclick = function() {  
    const time = new Date().toLocaleTimeString();  
    const message = `{"event":"h5Ready","time":"${time}"}`;  
    sendToApp(message);  
  };  
</script>  

<div>  
    <h1>H5 页面内容</h1>  
    <p id="app-msg">最新 App 消息: 暂无</p>  
    <button id="send-btn">H5 调用 App 弹窗</button>  
    <p id="h5-status"></p>  
</div>

总结

通过上述三个部分的协作,我们成功地在 uni-app 鸿蒙应用中搭建了 H5 页面和 App 之间的通信桥梁:

  1. App 侧 (UTS): 使用 WebInteractionModule 类和 WebComponent 的原生能力,通过 injectWebMessagePort 注入发送通道,通过 onWebMessage 接收 H5 消息。
  2. App 侧 (Vue): 使用 <web-view> 组件,并通过 onHarmonyWebComponentCreated 事件获取 WebComponent 实例,将其实例传递给 UTS 插件进行初始化和监听。
  3. H5 侧 (JS): 通过调用全局注入的 window.HarmonyAppBridge.postMessage() 发送消息给 App,并通过全局函数 window.receiveAppMessage() 接收 App 的指令。

全文完,欢迎点赞、收藏、转发!

2 关注 分享
DCloud_CHB 威龙

要回复文章请先登录注册