HarmonyOS鸿蒙应用开发——原生与H5通信框架DSBrigde-HarmonyOS

文章目录

介绍

HarmonyOS版的DSBridge,通过本库可以在鸿蒙原生与JavaScript完成交互,相互调用彼此的功能。

目前兼容Android、iOS第三方DSBridge库的核心功能,基本保持原来的使用方式,可以放心接入到项目中,后续会持续迭代保持与Android库相同的功能,减少前端和客户端的适配工作。

支持的功能:

  • 支持以类的方式集中统一管理API;
  • 支持同步和异步调用;
  • 支持进度回调/回传:一次调用,多次返回;
  • 支持API是否存在的测试 (当前仅支持检测原生API,在调用call()方法时会自检测)

暂不支持的功能:

  • 不支持API命名空间
  • 不支持JavaScript的事件侦听器关闭页面

源码:

由于DSBridge库作者已经停止维护了,Android端建议使用 https://github.com/751496032/DSBridge-Android ,目前本人在维护。

安装

text 复制代码
ohpm install @hzw/ohos-dsbridge

使用

原生

1、在原生新建一个类继承BaseBridge,实现业务API

, 通过类来集中统一管理API,方法用@JavaScriptInterface()标注,是不是很眼熟呢,加一个@JavaScriptInterface()标注主要为了使用规范,是自定义的装饰器,与Android保持一致性。

typescript 复制代码
export class JsBridge extends BaseBridge {
  private cHandler: CompleteHandler = null

  /**
   * 同步
   * @param p
   * @returns
   */
  @JavaScriptInterface(false)
  testSync(p: string): string {
    LogUtils.d("testSync: " + JSON.stringify(p))
    return "hello native"
  }

  /**
   * 异步
   * @param p
   * @param handler
   */
  @JavaScriptInterface()
  testAsync(p: string, handler: CompleteHandler) {
    LogUtils.d("testAsync: " + JSON.stringify(p))
    this.cHandler = handler
  }
}

其中方法中的形参CompleteHandler,可用于异步回调。

2、在原生Web初始化,通过API类将JS代理对象注入到JS中,如下:

typescript 复制代码
private controller: WebviewController = new webView.WebviewController()
private jsBridge = new JsBridge(this.controller)

Web({ src: this.localPath, controller: this.controller })
          .javaScriptAccess(true)
          .javaScriptProxy(this.jsBridge.javaScriptProxy)

)        

3、在JavaScript中通过dsBridge对象调用原生API,第一个参数是原生方法名称,第二参数是原生方法接收的参数,异步方法有第三个参数,是回调函数,会接收CompleteHandler异步回调结果。

typescript 复制代码
// 同步
let msg = dsBridge.call('testSync', JSON.stringify({data: 100}))

// 异步
dsBridge.call('testAsync', JSON.stringify({data: 200}), (msg) => {
  updateMsg(msg)
})

JavaScript

1、在JavaScript中初始化dsBridge,通过cdn或者npm安装都可以。

如果项目没有历史包袱,建议直接用m-dsbridge包。

复制代码
npm i m-dsbridge
// 或者cdn引入
<script src="https://cdn.jsdelivr.net/npm/m-dsbridge@1.0.0/dsBridge.js"></script>

或者直接用原Android或iOS的DSBridge库的JS脚本也行,可能会存在某些API不支持,前面已经有介绍了,但核心功能API是支持的。

2、通过dsBridge对象注册Js函数,供原生调用。

typescript 复制代码
// 注册同步函数
dsBridge.register('showAlert', function (a, b, c) {
        // return "原生调用JS showAlert函数"
         alert("原生调用JS showAlert函数" + a + " " + b + " " + c)
        return true
    })

// 注册异步函数
dsBridge.registerAsyn('showAlertAsync', function (a, b, c, callback) {
  let counter = 0
  let id = setInterval(() => {
    if (counter < 5) {
      callback(counter, false)
      alert("原生调用JS showAlertAsync函数" + a + " " + b + " " + c + " " + counter)
      counter++
    } else {
      callback(counter, true)
      alert("原生调用JS showAlertAsync函数" + a + " " + b + " " + c + " " + counter)
      clearInterval(id)
    }
  }, 1000)

})

其中异步的callback函数,如果最后一个参数返回true则完成整个链接的调用,false则可以一直回调给原生,这个就是JavaScript端的一次调用,多次返回。比如需要将JavaScript端进度数据不间断同步到原生,这时就可以派上用场了。

3、原生通过API实现类来调用JavaScript所注册的函数。

typescript 复制代码
Button("调用js函数-同步")
        .onClick(() => {
          this.jsBridge.callJs("showAlert", [1, 2, '666'], (v) => {
            this.msg = v + ""
          })
        })

      Button("调用js函数-异步")
        .onClick(() => {
          this.jsBridge.callJs("showAlertAsync", [1, 2, '666'], (v) => {
            this.msg = v + ""
          })
        })
    }

callJs()方法有三个形参,第一个是Js注册的函数名称,第二个是Js接收函数的参数,是一个数组类型,第三个是监听Js函数返回结果的函数。

另外也提供了与Android库一样调用函数callHandler()

进度回调

前面提到了JavaScript端的一次调用,多次回调的情况,在原生端也是支持的,还是有应用场景的,比如将原生的下载进度实时同步到js中,可以通过CompleteHandler#setProgressData()方法来实现。

typescript 复制代码
  @JavaScriptInterface()
  testAsync(p: string, handler: CompleteHandler) {
    LogUtils.d("testAsync: " + JSON.stringify(p))
    this.cHandler = handler
    let counter = 0
    setInterval(() => {
      if (counter < 5) {
        counter++
        handler.setProgressData("异步返回的数据--" + counter)
      } else {
        this.cHandler.complete("异步返回的数据--结束")
        this.cHandler.complete("异步返回的数据--结束2")
      }
    }, 1000)

JavaScript:

typescript 复制代码
dsBridge.call('testAsync', JSON.stringify({data: 200}), (msg) => {
  updateMsg(msg)
})

具体可以参考demo。

参考

相关推荐
JieE2126 小时前
LeetCode 226. 翻转二叉树|JS 递归超详细拆解,二叉树入门经典题
javascript·算法
JieE2127 小时前
LeetCode 104. 二叉树的最大深度|递归思路超详细拆解
javascript·算法
kyriewen10 小时前
我用 AI 一周写完了整个项目,上线第一天就崩了——这是我踩过最贵的 5 个坑
前端·javascript·ai编程
Larcher11 小时前
AI Loop:让AI像人一样自主完成任务的核心机制
javascript·人工智能·设计模式
默_笙11 小时前
🃏 JS 只有 8 种数据类型,但我花了 2 天才搞懂 null 和 undefined 的区别
javascript
jump_jump11 小时前
流式 HTML:从 htmx 片段装配到浏览器原生增量渲染
javascript·性能优化·前端工程化
swipe13 小时前
正则表达式入门到进阶:从表单校验到手写模板引擎
前端·javascript·面试
kyriewen13 小时前
前端错误监控最全指南:捕获 JS 异常、Promise 拒绝、资源加载失败,附上报代码
前端·javascript·监控
大家的林语冰14 小时前
ESLint 近期动态大全,新版本正式发布,antfu 大佬推荐的插件也更新了!
前端·javascript·前端工程化
胡志辉15 小时前
深入浅出 call、apply、bind
前端·javascript·后端