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

HarmonyOS ArkTS Web组件jsbridge

1. HarmonyOS ArkTS Web组件jsbridge

1.1. Web组件引入和调用JS库

  关于ts可以调用JS库,可以使用以下几种方式:文档中心:https://developer.huawei.com/consumer/cn/doc/harmonyos-faqs-V5/faqs-arkweb-kit-V5
在这里插入图片描述

1.1.1. 鸿蒙系统H5 JSBridge的优势

  相比其他移动操作系统,鸿蒙系统的H5 JSBridge具有以下优势:
  易用性:JSBridge提供了一套简单易用的API,使得前端开发人员可以方便地进行调用和交互。
  扩展性:开发人员可以根据自己的需求自定义原生模块,提供更多的功能和交互效果。
  跨平台支持:鸿蒙系统的JSBridge可以在不同的平台上使用,包括Android、iOS和Web等。

1.1.2. 鸿蒙系统H5 JSBridge的应用场景

  鸿蒙系统的H5 JSBridge可以应用于各种场景,包括但不限于:
  获取设备信息:开发人员可以使用JSBridge调用原生API获取设备的型号、操作系统版本等信息,以便进行针对性的优化和适配。
  调用原生功能:开发人员可以使用JSBridge调用原生功能,例如打开摄像头、获取位置信息等,以实现更多的功能和交互效果。
  数据传递和共享:JSBridge可以实现前端和原生之间的数据传递和共享,方便实现数据的同步和共享。

1.2. jsbridge

  文档地址:https://ohpm.openharmony.cn/#/cn/detail/@ncc%2Fjsbridge

1.2.1. 简介

  随着智能手机的普及,移动应用的需求日益增长。而在开发移动应用时,前端开发人员需要与原生平台进行交互,以实现更多的功能和优化用户体验。鸿蒙系统提供了一个强大的H5 JSBridge工具,使得前端开发人员可以方便地与鸿蒙系统进行通信和交互。
  JSBridge是一种将JavaScript代码和原生代码进行桥接的技术。它允许前端开发人员通过JavaScript调用原生代码,实现更多的功能和交互效果。鸿蒙系统的JSBridge提供了一套标准的API,方便开发人员进行调用。
  JSBridge 是基于 OpenHarmony Web 组件的 JavaScriptProxy 机制开发的三方库,提供了 bridge 形式的 ArkTS 和 JavaScript 相互调用接口。
  通过简单的函数注册和初始化后,便可以使用下面的接口进行 ArkTS 与 JavaScript 的相互调用:

// In ArkTS
jsbridge.post('jsFuncName', param1, param2, ...);
// In Javascript (Html)
jsbridge.call('etsFuncName', param1, param2, ...);

1.2.2. 下载安装

ohpm install @ncc/jsbridge

  OpenHarmony ohpm 环境配置等更多内容,请参考如何安装 OpenHarmony ohpm 包
  上面接口参数中出现自定义类型声明如下:

type SupportTypes = string | number | boolean;
type SupportMethod = (...params: SupportTypes[]) => void | SupportTypes;
type NotFoundHander = (funcName: string) => void | SupportTypes;

1.2.3. 使用示例

  下面一个简单的 Web 页面为例子,展示本库的使用:

import web_webview from '@ohos.web.webview'
import JSBridge from '@ncc/jsbridge'

@Entry
@Component
struct Index {
  @State message: string = "Show something"
  controller: web_webview.WebviewController = new web_webview.WebviewController()
  isReady: boolean = false;
  // 创建 JSBridge 实例
  jsbridge: JSBridge = new JSBridge(this.controller)
  build() {
    Column() {
      Row() {
        Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center }) {
          Text(this.message)
            .fontSize(18).fontWeight(700).fontColor('#000000')
        }
      }.padding({ left: 20, right: 20, bottom: 20, top: 0 }).width('100%') 
      Row() {
        Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center }) {
          Button("Call JS function").width('100%')
            .onClick((e) => {
              if (this.isReady) {
                // 通过 jsbridge.post('xxx', xxx) 调用 js 函数
                const str = "My string to call JS";
                this.jsbridge.post('changeWebMessage', str);
              }
            })
        }
      }
      Row() {
        // Web 组件
        Web({ src: $rawfile("example1.html"), controller: this.controller })
          // 此处使用的 onControllerAttached 是 API10 新增,API9 可以选用其它事件或在其它时机进行
          .onControllerAttached(() => {
            if (!this.isReady) {
              // 在 controller 与 web 关联后才能进行 bridge 的初始化
              this.jsbridge.initBridge();
              // 添加支持的方法
              this.jsbridge.register({ 'changeNativeMessage': this.changeNativeMessage });
              this.isReady = true;
            }
          })
      }.padding({ left: 20, right: 20, bottom: 20, top: 0 })
      .width('100%')
    }
  }
  // 一个本地 ArkTS 函数
  changeNativeMessage = (message: string) => {
    this.message = message;
  }
}
<!-- local.html -->
<!DOCTYPE html>
<html>
<body>
    <p>
        <input type="text" id="input" value="Message to Native">
    </p>
    <p>
        <button id="button"> Click to call ArkTS funcA() </button>
    </p>
    <div id="text">This is some message.</div>
    <script>
const button = document.getElementById("button");
const input = document.getElementById("input");
const text = document.getElementById("text");

button.addEventListener('click', function() {
  // 通过 jsbridge.call('xxx', xxx) 调用 ArkTS 函数
  jsbridge.call('changeNativeMessage', input.value);
});
function changeWebMessage(str) {
  text.innerHTML = str;
}
    </script>
</body>
</html>

  在上面的例子中,Web 端和应用端都有一个按钮用于彼此间的调用。
  (1)通过 jsbridge.post,应用端调用 Web 端的 js 函数,将 Web 端的 div 内的文本修改为 My string to call JS;
  (2)通过 jsbridge.call,Web 端调用应用端的 ArkTS 函数,将 Web 端上方的一行文本修改为 input 输入的内容。

1.2.4. 详细说明

  下面一个简单的 Web 页面为例子,展示本库的使用:

1.2.4.1. 引用库
import JSBridge from '@ncc/jsbridge'

  实例创建与关联
  创建的实例需要与一个 web_webview.WebviewController 关联。
  示例:

// 方式一:创建后关联
let jsbridge = new JSBridge();
jsbridge.attachController(webviewController);
// 方式二:创建时关联
let jsbridge = new JSBridge(webviewController);
Bridge初始化/移除

  初始化需要在 webviewController 与 Web 组件关联后。初始化会向 WebviewController 注册一个 Bridge Object,用于 Web 端调用本地 ArkTS 函数。
  示例如下:

try {
  // 传入参数为 Web 侧的 Bridge Object 名
  // 下面的示例中,初始化后,Web 侧可以使用下面的方式进行调用
  // jsbridgeName.call(xxx, ...)
  // Name 为可选参数,默认情况下为 'jsbridge'
  jsbridge.initBridge('jsbridgeName');
} catch (error) {
  // 如果在 controller 未与 Web 组件关联时调用会抛出错误
  console.log(error.message);
}

  想要取消这一注册,可以使用下面的接口:

try {
  jsbridge.removeBridge();
} catch (error) {
  console.log(error.message);
}

  注意:每次调用 initBridge 时,都会对 webviewController 进行一次刷新(使用 fresh 接口),因此请确保 initBridge 的调用时机在掌控中,或是它只会被调用一次,以避免造成不可控的影响。

1.2.4.2. 添加/移除可调用的应用侧函数

  可以使用 register 函数向 jsbridge 添加支持的函数。该函数可以多次调用。
  函数同名时,后注册的会覆盖先注册的。示例如下:

// 下面的注册完成后,我们可以在 Web 侧使用 js 调用这两个方法:
// jsbridgeName.call('functionA', 'this is a string', 1)
// jsbridgeName.call('funcB')
jsbridge.register({
  'functionA': functionA,
  'funcB': functionB,
});
// 方法可以有任意的参数数量
// 但是传入参数和返回值仅支持 string/number/boolean
// 对 Object 类型的传入/返回需求可以尝试用 JSON 序列化解决
function functionA(param1: string, param2: number) {
  // do something
}
function functionB() {
  // do something
}

  如果注册的是成员函数等需要上下文的函数,会存在上下文(this)丢失的风险。在定义时使用箭头函数或手动绑定实体是一种不错的解决方案:

class Student {
  name: string = "Alice";
  getName1() {
    return this.name;
  }
  getName2 = () => {
    return this.name;
  }
}
let stu = new Student;
jsbridge.register({'getName1': stu.getName1.bind(stu)});
jsbridge.register({'getName2': stu.getName2});

  移除函数可以使用 unregister 接口:

// 支持传入方法名列表
jsbridge.unregister(['getName1', 'getName2'])
// 也支持只传入一个方法名
jsbridge.unregister('getName1');
1.2.4.3. Web侧调用ArkTS

  通过 jsbridge.call,可以从 Web 侧调用已被注册的 ArkTS 函数:

jsbridge.call('etsFuncName', params);
1.2.4.4. (可选)配置回调函数

  在 Web 侧使用 jsbridge.call 时,如果调用的函数不被支持,call 会代替的以 notFoundHandler 作为回调函数。
  默认情况下,该 handler 会在控制台打印一条: “xxx is not found!”。
  可以通过下面的接口进行配置:

jsbridge.setNotFoundHandler(
// 传入的函数必须接收一个 string 参数
// 且返回值类型必须是 void | string | number | boolean
(funcName: string) => {return funcName + ’ is not found!';}
);
应用侧调用JS
JSBridge 还基于 WebviewController 的 runJavaScript 接口封装了 post 函数,用于应用侧调用 Web 侧函数。

// 支持直接传入 JS 代码
jsbridge.postJS("jsFunctionA('param1', 1, 2);");
// 也支持 post('xxx', xxx) 的调用形式
// 使用此接口传入的参数,都会被自动序列化后拼接起来
jsbridge.post('jsFunctionA', string1, number1, number2);
1.2.4.5. JS 异步调用 ArkTS 函数的实现方案

  本库基础实现的 jsbridge.call 是同步调用。因此我们在此处给出在 JS 侧进一步封装为基于 Promise 的异步调用的方案:

// 'jsbridge' 需替换为 init 时的 jsbridgeName
// 使用 AsyncJSBridge.callAsync(funcName, ...params) 就可以异步调用 Native 函数
const _JSBridge = self['jsbridge'];

const AsyncJSBridge = {
    call: (funcName, ...params) => {
        // 同步调用接口
        return _JSBridge.call(funcName, ...params);
    },
    callAsync: (funcName, ...params) => {
        // 异步调用接口
        return new Promise((resolve, reject) => {
            try {
                let res = _JSBridge.call(funcName, ...params);
                resolve(res);
            } catch (error) {
                reject(error);
            }
        });
    }
}

http://www.kler.cn/a/378060.html

相关文章:

  • oscp学习之路,Kioptix Level2靶场通关教程
  • 群晖Cloud Sync一键同步让数据管理变得简单
  • unipp中使用阿里图标,以及闭坑指南
  • C++模板:编译时模拟Duck Typing
  • Y3编辑器教程8:资源管理器与存档、防作弊设置
  • openwrt 负载均衡方法 openwrt负载均衡本地源接口
  • Hadoop-002-部署并配置HDFS集群
  • Codeforces Round 981 (Div. 3) (A~F)
  • Java入门10——封装(private)
  • 【Linux】--- 开发工具篇:yum、vim、gcc、g++、gdb、make、makefile
  • 萤石私有化设备视频平台EasyCVR视频融合平台如何构建农业综合监控监管系统?
  • 面试题整理 4
  • 阿里云docker安装禅道记录
  • TCP三次握手,四次挥手,以及11种状态详解
  • Oracle 第17章:数据字典与视图
  • python的数据结构列表方法及扩展(栈和队列)
  • InstructIR: High-Quality Image Restoration Following Human Instructions 论文阅读笔记
  • IDEA 好用的插件分享
  • Blender进阶:贴图与UV
  • 【C++篇】跨越有限与无限的边界:STL之set容器中的自我秩序与无限可能
  • 【踩坑】修复高版本dgl中distributed.load_partition不返回orig_id问题
  • nodejs入门教程19:nodejs dns模块
  • 第三百零五节 Log4j教程 - Log4j日志记录方法
  • Excel常用函数与操作
  • ArcGIS软件之“新建中学最适合地址”地图制作
  • 十款思维导图软件推荐,有适合你的一款!!!