搞定了 ArkWeb 的页面加载、生命周期管理、权限配置、网络白名单和缓存控制。到这里,你的鸿蒙混合项目已经能正常展示 H5、正常联网、不会内存泄漏、不会缓存错乱。

但——只能展示页面的混合应用,毫无实际业务价值。

真正的混合开发核心,只有一件事:让 H5 和鸿蒙原生互相调用、互相传值。

比如这些常见需求:

  • H5 点击按钮,调用鸿蒙原生弹窗、Toast、原生分享

  • H5 提交表单,调用原生获取设备信息、版本号、唯一标识

  • 鸿蒙原生主动向 H5 推送数据、推送登录状态、推送事件通知

  • H5 完成操作后,通知原生关闭页面、跳转原生页面

这些功能全部依赖 ArkWeb 双向通信机制,也就是大家常说的 JSBridge。

很多新手在这里踩巨多坑:调用没反应、参数传不过去、回调不触发、页面销毁后桥接报错、重复注册导致内存溢出、H5 端写法不兼容鸿蒙内核……

本篇我带你从零手写一套 HarmonyOS7 标准双向通信方案:原生注册方法给 H5 调用、H5 调用原生、原生主动调用 H5、异步回调返回结果,全程可直接落地项目。

没有过度封装、没有废话、全部是可上线代码。

前置必读:《Web 组件 H5 加载与生命周期管理》《权限、网络白名单与页面缓存控制》两篇生命周期 + 权限配置,本篇基于前两篇完整工程继续迭代。

一、先搞懂:鸿蒙 ArkWeb 双向通信原理

很多人学不懂 JSBridge,是因为完全搞反了调用逻辑。

我用最通俗的人话讲清楚:

1、原生 → H5:

鸿蒙是主人,H5是客人。主人可以随时主动喊话客人,通过 runJavaScript 执行 H5 全局 JS 方法。

2、H5 → 原生:

客人不能随便喊主人,必须主人提前“开放接口、登记方法”,H5 才能调用原生能力。

这个「登记方法」的动作,就是 registerJavaScriptProxy。

再记一个重中之重的版本区别:

HarmonyOS7 对桥接机制做了优化,和旧版鸿蒙语法略有区别,不能直接照搬网上旧代码!

旧版容易出现:注册失效、方法找不到、白屏、内核崩溃。

二、第一步:封装原生可被 H5 调用的工具类

我们需要写一个桥接工具类,专门暴露方法给前端 H5 调用。

规范非常重要:

  • 所有给 H5 调用的方法,必须加 @JavaScriptInterface

  • 方法必须 public

  • 不支持解构、不支持复杂参数、尽量用字符串传参

  • 禁止在桥接方法内写耗时同步操作,极易卡死 Web 内核

下面是项目可直接上线的工具类:

import { JavaScriptInterface } from '@kit.ArkWeb';
import { deviceInfo } from '@kit.BasicServicesKit';

export class JsBridgeModel {
  // 回调句柄,用于返回数据给H5
  public h5Callback: (result: string) => void | null;

  // 1. 获取设备基础信息(供H5调用)
  @JavaScriptInterface
  getDeviceInfo(): string {
    return JSON.stringify({
      deviceName: deviceInfo.deviceName,
      deviceType: deviceInfo.deviceType,
      productModel: deviceInfo.productModel
    });
  }

  // 2. 原生弹窗提示
  @JavaScriptInterface
  showNativeToast(msg: string): void {
    console.info("H5调用原生弹窗:", msg);
    // 项目中可替换为自己的Toast/Dialog组件
  }

  // 3. 带回调的原生方法(重点:H5传参、原生处理、返回结果)
  @JavaScriptInterface
  getNativeData(params: string): string {
    console.info("H5传入参数:", params);
    return JSON.stringify({
      code: 200,
      msg: "原生回调成功",
      data: "来自鸿蒙原生返回数据"
    });
  }
}

我简单解释三个方法的定位:

  • getDeviceInfo:无参返回设备信息,最基础的同步调用

  • showNativeToast:H5 控制原生 UI 行为

  • getNativeData:H5 传参、原生处理、同步返回结果,业务最常用

三、第二步:页面注册桥接对象,开启通信能力

写好了工具类不代表能用,必须在 Web 组件初始化时 注册到 Web 内核。

核心 API:registerJavaScriptProxy

参数说明(很多人搞不懂):

  • 参数1:你自定义的桥接实例对象

  • 参数2:H5 全局调用的对象名(前端通过这个名字调用)

  • 参数3:对外开放的方法名数组(严格白名单,不写就调用不到)

完整页面可运行代码(融合前两篇生命周期):

import { Web, WebController, WebLoadStatus, CacheMode } from '@kit.ArkWeb';
import { JsBridgeModel } from './JsBridgeModel';

@Entry
@Component
struct ArkWebBridgePage {
  private webController: WebController = new WebController();
  private jsBridge: JsBridgeModel = new JsBridgeModel();

  @State loadStatus: string = "页面待加载";

  aboutToAppear() {
    // 关闭缓存,保证调试最新页面
    this.webController.setCacheMode(CacheMode.None);
  }

  onPageShow() {
    this.webController.resume();
  }

  onPageHide() {
    this.webController.pause();
  }

  aboutToDisappear() {
    // 页面销毁必须清空桥接引用,防止内存泄漏
    this.jsBridge.h5Callback = null;
    this.webController.destroy();
  }

  build() {
    Column() {
      Text(`加载状态:${this.loadStatus}`)
        .fontSize(16)
        .margin(12)

      Web({
        src: "https://xxx你的测试H5地址/index.html",
        controller: this.webController
      })
      .width('100%')
      .height('85%')
      .javaScriptAccess(true) // 必须开启JS执行权限
      .registerJavaScriptProxy(
        this.jsBridge,
        "nativeBridge",
        ["getDeviceInfo", "showNativeToast", "getNativeData"]
      )
      .onLoadStatusChange((status) => {
        if (status === WebLoadStatus.StartLoading) {
          this.loadStatus = "开始加载H5页面";
        } else if (status === WebLoadStatus.FinishLoading) {
          this.loadStatus = "页面加载完成,桥接已就绪";
        } else if (status === WebLoadStatus.ErrorLoading) {
          this.loadStatus = "页面加载失败";
        }
      })
    }
    .width('100%')
    .height('100%')
  }
}

重点踩坑提醒:

必须开启 .javaScriptAccess(true)

不开启 JS 权限,桥接直接失效,前端调用全部无响应,控制台不报错,超级难排查。

四、第三步:H5 端调用鸿蒙原生(前端标准写法)

注册完成后,前端 H5 全局会多出一个对象:nativeBridge,就是我们刚才定义的名称。

前端直接调用即可,我给你 鸿蒙ArkWeb专用、无兼容问题的前端JS代码:

// 1. H5调用原生获取设备信息
function callNativeDeviceInfo() {
  let res = nativeBridge.getDeviceInfo();
  console.log("原生设备信息:", JSON.parse(res));
}

// 2. H5调用原生弹窗提示
function callNativeToast() {
  nativeBridge.showNativeToast("来自H5的调用提示");
}

// 3. H5传参调用原生并获取返回值
function callNativeParam() {
  let result = nativeBridge.getNativeData("我是H5传给原生的参数");
  console.log("原生返回结果:", JSON.parse(result));
}

调用顺序:

  1. H5 页面加载完成后再调用,防止桥接未初始化

  2. 所有参数建议用字符串传递,复杂数据 JSON 序列化

  3. 返回值统一 JSON 解析,保证前后端格式统一

五、第四步:鸿蒙原生主动调用 H5 方法(反向通信)

双向通信,一定包含两个方向:

H5 调原生 +原生调 H5

场景非常多:登录成功通知 H5、退出登录清空H5状态、原生扫码结果回传给H5、推送消息刷新页面。

原生调用 H5 核心 API:runJavaScript

首先前端 H5 提前定义好全局方法:

// H5全局方法,供鸿蒙原生调用
window.getNativeNotice = function(msg){
  console.log("鸿蒙原生通知H5:", msg);
  alert("收到原生消息:" + msg);
}

然后鸿蒙原生直接执行:

// 原生主动推送数据给H5
sendMsgToH5(){
  let params = "Hello 来自鸿蒙7原生推送";
  // 执行H5全局JS方法
  this.webController.runJavaScript(`getNativeNotice('${params}')`, (res) => {
    console.info("调用H5方法完成,返回:", res);
  })
}

这就实现了 原生主动控制H5页面。

六、高阶实战:带异步回调的完整通信方案(业务必备)

上面是同步调用,真实项目绝大多数是异步:比如 H5 调用原生扫码、原生定位、原生网络请求,耗时操作需要异步回调。

我直接给你可上线的异步桥接模板。

6.1 桥接类增加异步回调方法

@JavaScriptInterface
requestNativeAsync(msg:string):void{
  // 模拟原生异步耗时操作
  setTimeout(()=>{
    let result = JSON.stringify({
      code:200,
      data:"异步任务执行成功"
    })
    // 回调结果给H5
    if(this.h5Callback){
      this.h5Callback(result);
    }
  },1000)
}

6.2 页面初始化监听回调

aboutToAppear(){
  this.jsBridge.h5Callback = (res:string)=>{
    console.info("异步回调返回H5结果:",res)
  }
}

6.3 H5异步调用写法

// H5调用原生异步方法
nativeBridge.requestNativeAsync("请求原生异步任务");

至此,同步调用、异步回调、双向通信全部闭环。

七、高频踩坑汇总(全部是我实战踩过的坑)

坑1:忘记开启 javaScriptAccess(true)

表现:无报错、无响应、死活调不通。

坑2:注册方法名和H5调用名不一致

register 的白名单数组写什么,前端才能调什么,大小写严格区分。

坑3:页面不销毁桥接引用导致内存泄漏

一定要在 aboutToDisappear 清空回调、销毁 WebController。

坑4:H5加载完成前调用桥接

前端必须在 onload 之后再调用原生方法。

坑5:复杂对象直接传参

鸿蒙桥接只稳定支持字符串传参,对象必须 JSON 序列化。

八、本篇总结 + 课后实战任务

本篇我们彻底打通了 ArkWeb 混合开发的核心灵魂:双向JSBridge通信。

你现在掌握的能力:

  • 正确注册 HarmonyOS7 专属 Web 桥接对象

  • H5 调用原生同步方法、获取返回值

  • H5 调用原生异步任务、接收回调结果

  • 原生主动调用、通知、刷新 H5 页面

  • 规避 90% 新手桥接报错、内存泄漏、调用失效问题

实操指南:

  1. 自己新增一个原生方法:获取APP版本号,提供给H5调用

  2. 实现原生按钮点击,主动给H5推送一条自定义消息

  3. 页面销毁前后打印日志,观察桥接引用是否清空

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐