HarmonyOS NEXT开发进阶(六):HarmonyOS NEXT实现嵌套 H5 及双向通信

文章目录

    • 一、前言
    • 二、鸿蒙应用加载Web页面
      • 2.1 加载网络地址页面
      • 2.2 加载本地H5页面
    • 三、实现Web组件 H5 层与鸿蒙应用层进行相互通讯
      • 3.1 鸿蒙应用向 H5 页面发送数据
      • 3.2 H5页面向鸿蒙应用发送数据
    • 四、拓展阅读

一、前言

随着HarmonyOS NEXT的快速发展,越来越多的应用厂商选择加入鸿蒙生态阵营。然而,考虑到存量项目技术架构选型,如何设计一套兼容性更强的应用系统显得尤为重要,尤其针对面对多端应用市场,在前期iOSAndroid两端应用市场支持基础上再次接入鸿蒙生态,应用开发及维护成本均明显提升。为此,可考虑将应用主体功能部分剥离为H5应用,原生端通过容器嵌套方式接入H5主体应用方式,当涉及主体公共功能发生变更时,仅需维护H5项目即可,无需频繁上架应用市场。鸿蒙生态系统提供了一种原生与H5交互的机制,使得开发者可以在鸿蒙原生应用中嵌入H5页面,实现一次开发,多端运行的目标。

二、鸿蒙应用加载Web页面

2.1 加载网络地址页面

  1. module.json5中添加网络权限。

    "requestPermissions": [{"name": "ohos.permission.INTERNET"}
    ]
    
  2. 导入webview

    import web_webview from '@ohos.web.webview'
    
  3. 创建WebviewController

    controller: web_webview.WebviewController = new web_webview.WebviewController();
    
  4. 创建Web组件。

    Web({ src: "http://www.example.com/", controller: this.controller })
    

案例效果:

在这里插入图片描述

2.2 加载本地H5页面

  1. 在项目的 rowfile 中存放 html 代码

在这里插入图片描述

  1. 在 Web组件中使用 $rawfile 加载本地html

    Web({ src: $rawfile('webTo.html'), controller: this.controller })
    

三、实现Web组件 H5 层与鸿蒙应用层进行相互通讯

3.1 鸿蒙应用向 H5 页面发送数据

在创建的WebviewController中使用 runJavaScript() 方法可直接触发 H5 页面中的方法。

鸿蒙侧示例代码

controller: web_webview.WebviewController= new web_webview.WebviewController(); 
@State content: string = ""
@state input: string = ""
build(){ Column(){Column(){Text("H5层")Web({ src: $rawfile('webTo.html'),controller: this.controller }).onConfirm((e:any) => { console.log("shq1874009 > " + JSON.stringify(e))this.content = e['message']return true;})}.height("50%").margin({top: 10}).padding(10).border({width:1}).width("100%") Column(){Text("应用层")TextInput({placeholder:"请输入数据"}).onChange((e) =>{ this.input = e})Button("向H5层发送数据").onClick(()=>{this.controller.runJavaScript('sendText("AAA")}).margin(10)Row().width("100%").height(1).backgroundColor("#ddd").margin(10)Text("接收H5传递的内容:"+ this.content)}.height("50%").margin({top: 10}).padding(10).border({width:1}).width("100%") .......

同样也可以使用模板字符串拼接参数进行传参。

controller: web_webview.WebviewController= new web_webview.WebviewController(); 
@State content: string = ""
@state input: string = ""
build(){ Column(){Column(){Text("H5层")Web({ src: $rawfile('webTo.html'),controller: this.controller }).onConfirm((e:any) => { console.log("shq1874009 > " + JSON.stringify(e))this.content = e['message']return true;})}.height("50%").margin({top: 10}).padding(10).border({width:1}).width("100%") Column(){Text("应用层")TextInput({placeholder:"请输入数据"}).onChange((e) =>{ this.input = e})Button("向H5层发送数据").onClick(()=>{this.controller.runJavaScript('sendText("${this.input}")}).margin(10)Row().width("100%").height(1).backgroundColor("#ddd").margin(10)Text("接收H5传递的内容:"+ this.content)}.height("50%").margin({top: 10}).padding(10).border({width:1}).width("100%") .......

H5侧示例代码

<script>function toOnos() {let obj = {name: "张三", age: "20"}confirm(JSON.stringify(obj))}function sendText(){document.getElementById("divCon").innerText = "你好"}
</script>
<div><button onclick="to0nos()">给原生应用传递数据</button><div id="divCon" style="width: 100px;height: 100px;background: #ddd;margin-top: 20px;"></div>
</div>

案例效果

在这里插入图片描述

3.2 H5页面向鸿蒙应用发送数据

在鸿蒙原生代码侧使用 javaScriptProxy 方法向 h5 的 window 对象中注册方法,此处注册的对象名叫 JSBridge ,在该对象中写入了一个 nativeMethod 方法,h5 中直接调用 nativeMethod() 方法即可向原生发送消息。

H5侧
h5侧直接调用 window 对象下的 JSBridge.nativeMethod 方法,第一个参数对应原生侧对应的 channelName 方法名,第二个参数为 h5 自定义参数,可带入回调方法,供原生侧完成调用的回调结果。

示例代码如下:

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script src="./icsshosdk.js"></script><style>body {padding-top: 80px;}.title {background: #eee;line-height: 60px;text-align: center;margin-bottom: 50px;}.button {cursor: pointer;line-height: 45px;color: #fff;border-radius: 10px;left: 20%;width: calc(100% - 30px);text-align: center;background: #616bff;margin: 15px;}.button:active {background: #525dff;}</style><script>document.addEventListener('webActiveReceive', (e) => {console.log("luvi > " + JSON.stringify(e.detail));let { key, data } = JSON.parse(e.detail)switch (key) {case "changeBgColor":document.getElementById("idt").style = "background: #ffecea;color: #ff7361"break;case "changeBtColor":document.querySelectorAll(".button").forEach(el => {el.style = `background: ${data}`})break;default:break;}})</script><script>function openNativePage() {let params = {name: "LoginPage",success: function (res) {console.log("luviWeb > openNativePage success. " + res)},fail: function () {console.log("luviWeb > openNativePage fail.")}}window.JSBridge.nativeMethod("openNativePage", params)}function getCity() {let params = {success: function (res) {document.getElementById("cityName").innerText = `当前城市:${res}`},fail: function () {console.log("luviWeb > getCity fail.")}}window.JSBridge.nativeMethod("getCity", params)}</script>
</head><body><div style="width: 100%;"><p class="title" id="idt">JSBridge演示</p><div><p class="button" onclick="openNativePage()">跳转原生页面</p></div><div style="margin-top: 30px;"><p style="margin-left: 15px;" id="cityName">当前城市:</p><p class="button" onclick="getCity()">获取当前定位</p></div></div>
</body></html>

鸿蒙侧示例代码如下

import { webview } from '@kit.ArkWeb';export interface IParamsCallback {name: stringkey: stringsuccess: (data?: string) => voidfail: (data?: string) => void
}@Entry
@Component
export struct MyWeb {webController: WebviewController = new webview.WebviewController()webUrl: string | Resource = "";build() {Column() {Web({ src: this.webUrl, controller: this.webController }).javaScriptProxy({object: {nativeMethod: (channelName: string, paramsCallback: IParamsCallback) => {if (!channelName || !paramsCallback) {return}switch (channelName) {case "openNativePage":paramsCallback.success()console.log("luvi > h5调用 openNativePage 方法,携带参数" + paramsCallback.name)break;case "getCity":paramsCallback.success()console.log("luvi > h5调用 getCity 方法,携带参数" + paramsCallback.name)break;default:break;}},},name: 'JSBridge',methodList: ['nativeMethod'],controller: this.webController,}).fileAccess(true).domStorageAccess(true).zoomAccess(false).width("100%").height("100%")}}
}

示例结果如下:

在这里插入图片描述

四、拓展阅读

  • HarmonyOS webview
  • 前端页面调用应用侧函数
  • 应用侧调用前端页面函数
  • 建立应用侧与前端页面数据通道

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/892739.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux Top 命令 load average 指标解读

前言 作为平台开发的同学&#xff0c;维护平台稳定性是我们最基本的工作职责&#xff0c;下面主要介绍下top 命令里 &#xff0c;load average 这个指标如何去衡量机器负载程度。 概念介绍 load average 是系统在过去 1 分钟、5 分钟、15 分钟 的平均负载&#xff0c;它表示运…

物联网之传感器技术

引言 在数字化浪潮席卷全球的今天&#xff0c;物联网&#xff08;IoT&#xff09;已成为推动各行各业变革的重要力量。而物联网传感器&#xff0c;作为物联网感知层的核心技术&#xff0c;更是扮演着不可或缺的角色。它们如同人类的五官&#xff0c;能够感知物理世界中的各种信…

uni-app编写微信小程序使用uni-popup搭配uni-popup-dialog组件在ios自动弹出键盘。

uni-popup-dialog 对话框 将 uni-popup 的type属性改为 dialog&#xff0c;并引入对应组件即可使用对话框 &#xff0c;该组件不支持单独使用 示例 <button click"open">打开弹窗</button> <uni-popup ref"popup" type"dialog"…

OStree技术简介

官网&#xff1a;https://ostreedev.github.io/ostree/introduction/ 基于OStree技术的不可变系统是一种利用OStree技术构建的具有不可变特性的操作系统&#xff1a; 什么是OStree技术 OStree是一个用于操作系统和容器二进制部署及更新的技术&#xff0c;它结合了类似Git的模…

国产编辑器EverEdit - 扩展脚本:新建同类型文件(避免编程学习者反复新建保存练习文件)

1 扩展脚本&#xff1a;在当前文件目录下新建同类型文件 1.1 应用场景 用户在进行编程语言学习时&#xff0c;比如&#xff1a;Python&#xff0c;经常做完一个小练习后&#xff0c;又需要新建一个文件&#xff0c;在新建文件的时候&#xff0c;不但要选择文件类型&#xff0c…

SparrowRTOS系列:链表版本内核

前言 Sparrow RTOS是笔者之前写的一个极简性RTOS&#xff0c;初代版本只有400行&#xff0c;后面笔者又添加了消息队列、信号量、互斥锁三种IPC机制&#xff0c;使之成为一个较完整、堪用的内核&#xff0c;初代版本以简洁为主&#xff0c;使用数组和表作为任务挂载的抽象数据…

C#使用OpenTK绘制3D可拖动旋转图形三棱锥

接上篇,绘制着色矩形 C#使用OpenTK绘制一个着色矩形-CSDN博客 上一篇安装OpenTK.GLControl后,这里可以直接拖动控件GLControl 我们会发现GLControl继承于UserControl //// 摘要:// OpenGL-aware WinForms control. The WinForms designer will always call the default//…

Oracle查询-in条件超过1000

目录 1.不分页 2.分页 oracle数据库中&#xff0c;in的查询条件超过1000的话&#xff0c;就会报错&#xff0c;应该怎样处理这样的情况呢&#xff1f; 1.不分页 把查询条件分成几个list&#xff0c;每个list有1000个数据&#xff0c;有几个list查询几次数据库就行了 2.分…

Android Room 报错:too many SQL variables (code 1 SQLITE_ERROR) 原因及解决方法

报错信息&#xff1a; android.database.sqlite.SQLiteException: too many SQL variables (code 1 SQLITE_ERROR): while compiling: SELECT * FROM points WHERE id IN (?,?,?,...,?,?,?)SQLiteException: too many SQL variables 通常是由于一次查询或插入的 SQL 语句…

ctf竞赛

在CTF&#xff08;Capture The Flag&#xff09;竞赛中&#xff0c;前端开发和后端开发都非常重要&#xff0c;二者各有其关键作用&#xff0c;很难简单地说哪个更重要&#xff0c;以下是具体分析&#xff1a; 前端开发的重要性 用户体验与交互&#xff1a;CTF竞赛平台的前端是…

【Vue】点击侧边导航栏,右侧main对应显示

需求&#xff1a;点击侧边导航栏&#xff0c;右侧main对应显示 通过v-if或v-show等指令来控制不同内容的显示隐藏来实现 注意&#xff1a; 使用v-if时候进行导航栏切换&#xff0c;右侧显示区域可能会出现样式错乱&#xff1b;使用v-show则不会出现此错误 <template>&…

JAVA:利用 RabbitMQ 死信队列实现支付超时场景的技术指南

1、简述 在支付系统中&#xff0c;订单支付的超时自动撤销是一个非常常见的业务场景。通常用户未在规定时间内完成支付&#xff0c;系统会自动取消订单&#xff0c;释放相应的资源。本文将通过利用 RabbitMQ 的 死信队列&#xff08;Dead Letter Queue, DLQ&#xff09;来实现…

特制一个自己的UI库,只用CSS、图标、emoji图 第二版

图&#xff1a; 代码&#xff1a; index.html <!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>M…

1.14 互斥与同步

1.思维导图 2.有一个隧道&#xff0c;长1000m&#xff0c;有一辆高铁&#xff0c;每秒100米&#xff1b;有一辆快车&#xff0c;每秒50米&#xff1b;要求模拟这两列火车通过隧道的场景。 1>程序代码&#xff1a; #include <stdio.h> #include <string.h> #i…

solidity基础 -- 枚举

在智能合约开发领域&#xff0c;Solidity语言因其简洁高效而被广泛使用。其中&#xff0c;枚举&#xff08;enum&#xff09;作为一种特殊的数据类型&#xff0c;为合约的状态管理提供了极大的便利。本文将通过一个具体的Solidity合约示例&#xff0c;深入探讨枚举的定义、使用…

14.STM32F407ZGT6-SPI

参考&#xff1a; 1.正点原子 前言&#xff1a; SPI一般用在中高速的外围器件上&#xff0c;如FLASH, GPS模块等。很常用的一种通信方式&#xff0c;学习总结很有必要。 1.SPI的概念及时序。 2.通过SPI操作Flash芯片。 37.1 SPI 及 NOR Flash 介绍 37.1.1 SPI 介绍 我们将从…

基于SpringBoot的中华诗词赏析文化交流平台

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码、微信小程序源码 精品专栏&#xff1a;…

44.ComboBox的数据绑定 C#例子 WPF例子

固定最简步骤&#xff0c;包括 XAML&#xff1a; 题头里引入命名空间 标题下面引入类 combobox绑定资源属性和选择属性&#xff0c;block则绑定和combobox一样的选择属性 C#&#xff1a; 通知的类&#xff0c;及对应固定的任务 引入字段 引入属性 其中资源是只读的 选…

Flink类加载机制详解

1. 总览 在运行Flink应用时,它会加载各种类,另外我们用户代码也会引入依赖,由于他们依赖版本以及加载顺序等不同,就可能会导致冲突,所以很要必要了解Flink是如何加载类的。 根据加载的来源的不同,我们可以将类分为三种: Java Classpath:Java类路径下,这是Java通用的…

水下通信:特点、主要应用与典型系统

引言 海洋覆盖了地球表面的71%&#xff0c;是地球上最大的生态系统。随着人类对海洋资源的不断探索和开发&#xff0c;水下通信成为了连接水下设备与陆上控制中心、实现水下数据交换和远程监控的关键技术。水下通信不仅在水下科研、资源开发、环境监测、水下救援等领域发挥着重…