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

HarmonyOS WebView

HarmonyOS WebView

  • Web组件提供基础的前端页面加载的能力,包括加载网络页面、本地页面、html格式文本数据。
  • Web组件提供丰富的页面交互的方式,包括:设置前端页面深色模式,新窗口中加载页面,位置权限管理,Cookie管理,应用侧使用前端页面JavaScript等能力。

注意:使用 webview 一定要去开启网络权限,否则页面将无法加载

1.创建一个简单的 webview 页面

1.1 app端 创建 webview 页面

// 1. 引入依赖
import { webview } from '@kit.ArkWeb';// 2. 创建webview控制器
@State message: string = 'webview page'
private controller: WebviewController = new webview.WebviewController()build () {Column ({ space: 15 }) {Text( this.message ).fontSize( 50 ).fontWeight( FontWeight.Bold )// 2. 利用 Web 组件引入对应的 Web端 内容Web({ src: '自己本地随便启动一个项目地址', controller: this.controller }).width('80%').height(400).backgroundColor('#11dd00')}.height( '100%' ).width( '100%' )
}

2.app端 输出 h5 的日志

  • 正常情况下我们开发会有很多日志输出,开发过webview的同学都知道,h5的日志不太好看,除非使用Vconsole插件
  • 鸿蒙对这个情况做的比较好,可以直接在app端的日志输出h5的日志
  • 使用webvivew属性 OnConsole 监听h5的console.log输出,并在控制台输出日志
Web({ src: '自己本地随便启动一个项目地址', controller: this.controller }).width('80%').height(400).backgroundColor('#11dd00').border({width: 1,radius: 5,style: BorderStyle.Solid}).onConsole((event) => {console.log('wuwuwu h5 打印的日志 => ', event?.message.getMessage())return true})

3.h5 和 app端 方法调用(数据传递)

  • 方法1:在鸿蒙中 h5 和 app端的交互是通过 window 来进行的
    • h5 把方法挂载到 window 对象上,app端 可以通过固定方法调用
    • app端 也可以通过固定api 把方法挂载到 window 对象上让 h5 调用。
    • 如果要做数据传递,在方法中加上返参或者回调即可
  • 方法2:可以通过双向数据通道进行数据传递
    • 实际上就是通过 postMessage

3.1 app端 调用 h5 的方法

3.1.1 h5 挂载方法到 window 对象上
// 在 h5 中,监听window.onload事件,挂载方法 testA 到 window 对象上
window.onload = () => {window.testA = () => {console.log('testFn 方法被调用')}
}
3.1.2 app端 调用 h5 的方法
// app端 创建一个按钮,通过按钮触发 h5 中的 testA 方法
Button('调用h5按钮').onClick(() => {// 使用 webview 控制器中的方法 runJavaScript 调用 h5 中的 testA 方法this.controller.runJavaScript('testA()')console.log('wuwuwu => 1. 调用 testFn 方法')})

3.2 h5 调用 app端 的方法

3.2.1 app端 挂载方法到 window 对象上
  • app端 需要创建一个事件对象
  • 通过固定api挂载到 window对象上
    • 根据api可以分为两种方式
3.2.1.1 创建事件对象
// 通过 class 创建一个全局公共类,里面包含一个方法 testB 
class ToWebObject {constructor() {}public testB() {console.log('wuwuwu 我是 App端 的打印信息 => App端 的 testB 函数被调用了')}
}
3.2.1.2 使用 web 属性 javaScriptProxy 挂载方法到 window 对象上
// app端 
// 创建要挂载的内容
@State sendObject: ToWebObject = new ToWebObject()Web({ src: '自己本地随便启动一个项目地址', controller: this.controller }).width('80%').height(400).backgroundColor('#11dd00').border({width: 1,radius: 5,style: BorderStyle.Solid}).onConsole((event) => {console.log('wuwuwu h5 打印的日志 => ', event?.message.getMessage())return true}).javaScriptProxy({// 挂载的事件对象object: this.sendObject,// 挂载到 window 对象上的属性名name: 'wuwuwu',// 注册的方法名,只有在这个数据中的方法 h5 才可以调用// 比如 object 中有两个方法 testA 和 testB,h5 只能调用 testB 方法methodList: ['testB'],controller: this.controller})
3.2.1.3 使用 webview 控制器的方法 registerJavaScriptProxy 挂载方法到 window 对象上,使用此方法后必须调用 refresh,方法才能生效
// app端 
// 创建要挂载的内容
@State sendObject: ToWebObject = new ToWebObject()
// 控制器
private controller: WebviewController = new webview.WebviewController()// web 组件
Web({ src: '自己本地随便启动一个项目地址', controller: this.controller }).width('80%').height(400).backgroundColor('#11dd00').border({width: 1,radius: 5,style: BorderStyle.Solid}).onConsole((event) => {console.log('wuwuwu h5 打印的日志 => ', event?.message.getMessage())return true})// 新建俩按钮用来挂载事件
Row() {Button('注册一些事件').onClick(() => {this.controller.registerJavaScriptProxy(this.sendObject,'wuwuwu',['testB'],)})Button('刷新一下激活事件').onClick(() => {this.controller.refresh()})
}
3.2.1.4 使用 webview 控制器的方法 registerJavaScriptProxy 挂载方法到 window 对象上,可以在声明周期 onControllerAttached 上调用该方法,此时 h5 还未加载
Web({ src: '自己本地随便启动一个项目地址', controller: this.controller }).width('80%').height(400).backgroundColor('#11dd00').border({width: 1,radius: 5,style: BorderStyle.Solid}).onConsole((event) => {console.log('wuwuwu h5 打印的日志 => ', event?.message.getMessage())return true}).onControllerAttached(() => {this.controller.registerJavaScriptProxy(this.sendObject,'wuwuwu',['testB'],)// 这块有个问题 ,在这个声明周期中调用onControllerAttached,在不调用refresh的情况下 h5 可以正常调用testB// 官方文档中只是说 onControllerAttached 必须要调用 refresh,才能生效// 这里不知道是有真的问题 或者是 官方文档没有跟新这部分内容// 我猜测是因为这个生命周期的时候 h5 还没有加载导致,,相当于 refresh 的作用this.controller.refresh()})
3.2.1.5 h5 调用方法,不管 app端 咋么调用,h5 都通过 window 对象来调用
// h5
// 直接调用 window 方法就行
// window.挂载时的name.要调用的方法名
window.wuwuwu.testB()

3.3 建立 app端 和 h5 双向数据通道

  • 1.创建双向数据通道接口

    • 使用的 API
      • webview 控制器方法 createWebMessagePorts()
    • 返回值:
      • 是一个数组, 数组内有两个接口 [ 接口1, 接口2 ]
      • [0] : 提供给 h5端 使用的, 需要传递给 h5端, h5端 使用这个接口去监听 App端 发来的消息, 同时也是使用这个接口向 App 端发送消息
      • [1] : 提供给 App端 使用的, App端 使用这个接口去监听 h5端 发来的消息, 同时也是使用这个接口向 h5端 发送消息
  • 2.把属于 h5端 的接口传递过去

    • 注意: 此时不是 App端 和 h5端 建立好通道传递
      • 而是先把建立通道的 “工具” 传递过去
      • 所以, 此时是 App端 给 window 发送一个消息( 而不是和 h5端 建立通道连接 )
  • 3.建立通道

    • 使用 webview 控制器方法 postMessage 把 “接口工具” 发过去
    • App端 和 h5端 都利用 “接口工具” 去建立双向连接通道
3.3.1 创建创建双向数据通道接口,并完成事件监听
  • 双向通道数据接口通过 webview 控制器方法 createWebMessagePorts() 创建
// ---------- app端 
// 变量private controller: WebviewController = new webview.WebviewController()
private posts: webview.WebMessagePort[] = []
private appPort: webview.WebMessagePort = Object()registerPortMessage() {this.posts = this.controller.createWebMessagePorts()// this.posts === [ h5端使用的接口, App端使用的接口 ]this.appPort = this.posts[1]// 把 h5 使用的接口传递给 h5this.controller.postMessage('__init__port__', [this.posts[0]], '*')// 监听 h5 发送的消息this.posts[1].onMessageEvent((event) => {this.messageEventHandle(event)})
}messageEventHandle(event: webview.WebMessage) {const resultInfo = JSON.parse(event as string) as ResultInfoTypeif (resultInfo.message === '__awu__') {console.log('wuwuwu app 端 接收到数据了', resultInfo.info.username, resultInfo.info.password, resultInfo.info.msg)// 接收到数据之后,告诉 h5 我接收到了数据this.appPort.postMessageEvent(JSON.stringify({message: '__awu__',info: '我接收到数据了'}))}
}// ----------h5端 
// 变量 
const count = ref(0)
const webPort = ref()// 监听 window 消息
window.addEventListener('message',(event)=>{// data 需要和 app端 发送消息的一致if(event.data === '__init__port__' && event.ports[0] !== null){// 表示发来的消息是 __init__port__// 并且携带了属于 h5端 的那个接口webPort.value = event.ports[0]// 至此, 你需要给 App端 发送消息的时候, 就可以使用 webPort 发送消息// 利用接口工具建立连接通道// 利用接口工具建立连接通道, 利用的事 App端 发送过来的接口工具webPort.value.onmessage = (event:any) => {// 接收到 App端 发送的消息 事件处理console.log('messageEventHandler',event.data)}}
})
3.3.2 发送消息
  • 发送消息通过 通道 发送
// app端 
Button('发送点信息').onClick(() => {// 1. 发送数据// this.appPort.postMessageEvent(JSON.stringify({//   message: '__awu__',//   info: '按钮发送的数据'// }))// 2. 发送数据this.appPort.postMessageEvent('按钮发送的数据')})// h5 端
const sendMessage = ()=>{webPort.value.postMessage(JSON.stringify({message: '__awu__',info: { username: 'admin', password: '1234567',msg:`这是发送的第${count.value}消息` }}))count.value++
}

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 学习STM32(6)-- STM32单片机ADCDAC的应用
  • NFS文件共享
  • Unity WebGL平台Hybrid Generate All报错undefined symbol sendfile
  • 大语言模型与多模态大模型loss计算
  • Gin框架接入pyroscope完美替代pprof实现检测内存泄露
  • 离职保密协议是什么?怎么样才是合法的?如何维护公司权益?
  • DataGear 企业版 1.2.0 发布,数据可视化分析平台
  • django常用的组合搜索组件
  • 【区块链+金融服务】山西省信易贷平台 | FISCO BCOS应用案例
  • redis面试(九)锁重入和互斥
  • 基于PCA-BP的数据多变量回归预测 Matlab代码(多输入单输出)[可显示原始特征贡献率+贡献率排序+累计贡献率]
  • 【Git】远程仓库新建分支后,拉到本地开发
  • 音视频概要
  • 主机防火墙测试--IPV6地址TCP/UDP/ICMP协议测试方法
  • 应对FingerprintJS反爬:Selenium的破解策略与技术详解
  • 【108天】Java——《Head First Java》笔记(第1-4章)
  • Apache的基本使用
  • HTTP--网络协议分层,http历史(二)
  • JavaScript类型识别
  • js如何打印object对象
  • JS专题之继承
  • Storybook 5.0正式发布:有史以来变化最大的版本\n
  • 阿里云Kubernetes容器服务上体验Knative
  • 闭包--闭包作用之保存(一)
  • 不发不行!Netty集成文字图片聊天室外加TCP/IP软硬件通信
  • 道格拉斯-普克 抽稀算法 附javascript实现
  • 技术胖1-4季视频复习— (看视频笔记)
  • 码农张的Bug人生 - 见面之礼
  • 前端存储 - localStorage
  • 如何学习JavaEE,项目又该如何做?
  • 算法-插入排序
  • 系统认识JavaScript正则表达式
  • 云栖大讲堂Java基础入门(三)- 阿里巴巴Java开发手册介绍
  • 如何通过报表单元格右键控制报表跳转到不同链接地址 ...
  • ​浅谈 Linux 中的 core dump 分析方法
  • ###STL(标准模板库)
  • #Datawhale AI夏令营第4期#AIGC方向 文生图 Task2
  • (02)Hive SQL编译成MapReduce任务的过程
  • (06)金属布线——为半导体注入生命的连接
  • (10)Linux冯诺依曼结构操作系统的再次理解
  • (17)Hive ——MR任务的map与reduce个数由什么决定?
  • (day18) leetcode 204.计数质数
  • (二)hibernate配置管理
  • (附源码)python房屋租赁管理系统 毕业设计 745613
  • (每日一问)基础知识:堆与栈的区别
  • (入门自用)--C++--抽象类--多态原理--虚表--1020
  • (三) diretfbrc详解
  • (四)事件系统
  • (小白学Java)Java简介和基本配置
  • (一)插入排序
  • .NET Core 将实体类转换为 SQL(ORM 映射)
  • .net core 源码_ASP.NET Core之Identity源码学习
  • .NET 事件模型教程(二)
  • .NET/C# 解压 Zip 文件时出现异常:System.IO.InvalidDataException: 找不到中央目录结尾记录。
  • [] 与 [[]], -gt 与 > 的比较