您现在的位置是:首页 >技术交流 >【鸿蒙】鸿蒙原生arkUI和H5交互网站首页技术交流

【鸿蒙】鸿蒙原生arkUI和H5交互

qq_22015625 2025-02-14 12:01:03
简介鸿蒙jsbridge[harmony]不存在

效果图

1、arkUI加载h5页面,设置 jsBridge,设置请求拦截器(onInterceptRequest)等

    NavDestination(){
      NavigationBar({ title: 'h5', rightTitle: '发数据给H5', rightCallBack: () => {
            // 向h5发送数据
           this.jsBridge.callback(1, 'Hello H5')
      } })
      Web({
        src: $rawfile('index.html'),
        controller: this.webController
      })
        .onPageBegin(() => {
          this.jsBridge.initJsBridge()
        })
        // .onInterceptRequest((event) => {
        //   return interceptRequest(event)
        // })
        .javaScriptAccess(true)
        .domStorageAccess(true)
        .javaScriptProxy(this.jsBridge.javaScriptProxy)
        .fileAccess(true)
        .width('100%')
        .height('100%')
        .mixedMode(MixedMode.All)
        .zoomAccess(false)
        .nestedScroll({
          scrollForward: NestedScrollMode.PARENT_FIRST,
          scrollBackward: NestedScrollMode.SELF_FIRST,
        })

    }.hideTitleBar(true)

1.0、封装的JsBridge


export class JsBridge {
  controller: webview.WebviewController;

  constructor(controller: webview.WebviewController) {
    this.controller = controller;
  }

  /**
   * 将 JavaScript 对象注window,并在window中调用函数。
   *
   * @returns javaScriptProxy.
   */
  get javaScriptProxy(): JavaScriptItem {
    let result: JavaScriptItem = {
      object: {
        call: this.call
      },
      name: 'JSBridgeHandle',
      methodList: ['call'],
      controller: this.controller
    }
    return result;
  }

  /**
   * JsBridge初始化
   */
  initJsBridge(): void {
    this.controller.runJavaScript(code);
  }

    // 收到来自h5的数据
  call = (func: string, params: string): void => {
    let paramsObject: ParamsItem = JSON.parse(params)
    let result: Promise<string> = new Promise((resolve) => resolve(''));
    switch (func) {
      case 'getH5Content':
        result = this.openAlert(paramsObject as ParamsItem);
        console.log('---', paramsObject)
        break;
      default:
        break;
    }
    result.then((data: string) => {
      this.callback(paramsObject?.callID, data);
    })
  }
  /**
   * 使用 runJavaScript 调用 WebView。
   */
  callback = (id: number, data: string): void => {
    this.controller.runJavaScript(`JSBridgeCallback('${id}', ${JSON.stringify(data)})`);
  }

  openAlert = (params: ParamsItem): Promise<string> => {
    AlertDialog.show({ message: params.data.content })
    return new Promise((resolve) => {
      resolve('success');
    })
  }

}
1.0.0、其中code可以封装到constant/CodeConstant.ets目录,代码如下
export const code = `
  // 定义一个对象,用于存储回调函数,键为调用ID
  const JSBridgeMap = {};
  // 初始化调用ID为0
  let callID = 0;

  /**
   * JSBridge回调函数
   * 当原生端调用此函数时执行
   * @param {number} id - 调用ID,用于查找对应的回调函数
   * @param {any} params - 原生端返回的参数
   */
  function JSBridgeCallback (id, params) {
    // 执行对应的回调函数,并传入参数
    JSBridgeMap[id](params);
    // 回调函数执行后,清除该回调函数
    JSBridgeMap[id] = null;
    delete JSBridgeMap[id];
  }

  // 定义一个对象,提供与原生端通信的方法
  window.ohosCallNative = {
    /**
     * 调用原生端方法
     * @param {string} method - 要调用的原生方法名
     * @param {any} params - 传递给原生端的参数
     * @param {Function} callback - 调用原生端方法后的回调函数,默认为空函数
     */
    callNative(method, params, callback) {
      // 生成唯一的调用ID
      const id = callID++;
      // 构造参数对象,包含调用ID和数据
      const paramsObj = {
          callID: id,
          data: params || null
      }
      // 将回调函数存储在JSBridgeMap中,以便原生端调用
      JSBridgeMap[id] = callback || (() => {});
      // 调用原生端方法,并将参数对象序列化后传入
      JSBridgeHandle.call(method, JSON.stringify(paramsObj));
    }
  }
`;
1.0.1、JavaScriptItem代码如下
/**
 * 定义一个调用类型接口,用于规范调用函数的方式
 * 这个接口主要用来统一调用方法的签名,确保调用的一致性和类型安全
 */
export interface callType {
  /**
   * 调用具体功能的方法
   * @param func 要调用的函数名称
   * @param params 调用函数时传递的参数
   */
  call: (func: string, params: string) => void
}

/**
 * 定义一个JavaScript项接口,用于描述JavaScript对象及其相关属性
 * 这个接口主要用于在Web视图中与JavaScript交互时,提供一种类型安全的方式来组织和管理JavaScript对象
 */
export interface JavaScriptItem {
  /**
   * 包含调用方法的对象,通过这个对象可以调用JavaScript中的方法
   */
  object: callType,
  /**
   * JavaScript对象的名称,用于标识该对象
   */
  name: string,
  /**
   * 方法列表,列出了该对象中所有可调用的JavaScript方法名称
   */
  methodList: Array<string>,
  /**
   * Web视图控制器,用于管理与JavaScript对象的交互
   */
  controller: WebviewController
}

1.0.2、ParamsItem 代码如下

/**
 * 定义参数项接口
 * 用于描述API调用的参数格式
 */
export interface ParamsItem {
  // 调用标识符,用于唯一标识一次调用
  callID: number,

  // 参数数据项,包含具体的参数信息
  data: ParamsDataItem
}


export interface ParamsDataItem {
  name?: string;
  url?: string
  content?: string;
}

export interface FileItem {
  fileName: string;
  filePath: string
}

2.0、H5示例代码

// index.html
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
    <title>测试</title>
    </script>
</head>
<body>
	<header class="header">

	</header>
	<div class="box">
		<div style="color: blue;" onclick="openHMAlert()">调用arkUI的弹框,并传递一个弹框内容“来自H5”</div>
		<div id="concat_tip"></div>
	</div>

</body>
<script type="text/javascript" charset="utf-8">
	function openHMAlert() {
        // 给原生发送数据
		window.ohosCallNative.callNative('getH5Content', { content: '来自H5' });
	}

    // 接收来自原生的数据
	JSBridgeCallback = (id, text) => {
  		document.getElementById('concat_tip').innerHTML = text
	}
</script>
</html>

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。