【鸿蒙HarmonyOS Next实战开发】Web组件H5界面与原生交互-抽奖页面

想必很多人都经历过这样的情况:当我们点击某个应用的页面时,往往会跳转到一个类似于浏览器加载的页面,只有等到加载完成之后,才会呈现出该页面的具体内容。通常情况下,加载和显示网页的任务都是由浏览器来完成的。

而ArkUI为我们提供了Web组件,借助这一组件,我们就可以在自己的应用程序中轻松嵌入一个"浏览器",从而便捷地展示各种各样的网页内容。

图1web组件示例图

本文将为您介绍Web组件一些常用API的使用。

Web组件介绍

本文将为您介绍Web组件的一些常用API的使用方法。

Web组件是一种具备网页显示能力的组件。它依赖两个关键参数:src资源地址和controller控制器。其中,src资源地址既支持本地资源,也支持网络资源;controller控制器由@ohos.web.webview提供,用于控制Web组件的各种行为。

参数名 参数类型 必填 参数描述
src ResourceStr 网页资源地址。如果访问本地资源文件,使用$rawfile或者resource协议。如果加载应用包外沙箱路径的本地资源文件,使用file://沙箱文件路径。
controller WebviewController 控制器。可以控制Web组件的各种行为,如网页前进、后退等
[表1Web组件参数介绍]

通过$rawfile加载本地资源

对于src参数,如果需要加载本地网页,可以通过$rawfile加载本地资源文件。

TypeScript 复制代码
import { webview } from '@kit.ArkWeb';

@Entry
@Component
struct WebComponent {
  controller: webview.WebviewController = new webview.WebviewController()
  build() {
    Column() {
      // 通过$rawfile加载本地资源文件。
      Web({ src: $rawfile("index.html"), controller: this.controller })
    }
  }
}

通过resource协议加载本地资源文件

对于src参数,如果需要加载本地网页,也可以通过resource协议加载本地资源文件。

TypeScript 复制代码
import { webview } from '@kit.ArkWeb';

@Entry
@Component
struct WebComponent {
  controller: webview.WebviewController = new webview.WebviewController()
  build() {
    Column() {
      // 通过resource协议加载本地资源文件。
      Web({ src: "resource://rawfile/index.html", controller: this.controller })
    }
  }
}

加载在线网页

对于src参数,如果需要加载在线网页,可以直接传入对应的网页地址。

TypeScript 复制代码
import { webview } from '@kit.ArkWeb';

@Entry
@Component
struct WebComponent {
controller: webview.WebviewController = new webview.WebviewController()
build() {
Column() {
Web({ src: 'www.example.com', controller: this.controller })
}
}
}

如果需要访问在线网页,需要在module.json5文件中添加网络权限:ohos.permission.INTERNET。

TypeScript 复制代码
"module": {
"requestPermissions": [
{"name": "ohos.permission.INTERNET"}
]
}

Webview的基本使用

@ohos.web.webview是系统提供的基础能力,提供了许多web控制的能力。例如,WebMessagePort、 WebviewController等。

名称 说明
WebMessagePort 通过WebMessagePort可以进行消息的发送以及接收。
WebviewController 通过WebviewController可以控制Web组件各种行为。
WebCookieManager 通过WebCookie可以控制Web组件中的cookie的各种行为
... ...
[表2Webview能力介绍]

WebviewController

通过WebviewController可以控制Web组件各种行为。一个WebviewController对象只能控制一个Web组件,且必须在Web组件和WebviewController绑定后,才能调用WebviewController上的方法(静态方法除外)。

WebviewController下包含runJavaScript、 registerJavaScriptProxy、 createWebMessagePorts等接口。

接口名称 说明
runJavaScript 异步执行JavaScript脚本,并通过回调方式返回脚本执行的结果。runJavaScript需要在loadUrl完成后,比如onPageEnd中调用。
registerJavaScriptProxy 注入JavaScript对象到window对象中,并在window对象中调用该对象的方法。
createWebMessagePorts 创建Web消息端口
[表3WebviewController接口介绍]

ArkTS调用H5

runJavaScript(script: string): Promise<string>

异步执行JavaScript脚本,并通过Promise方式返回脚本执行的结果。runJavaScript需要在loadUrl完成后,比如onPageEnd中调用。

TypeScript 复制代码
import { webview } from '@kit.ArkWeb';
import { BusinessError } from '@kit.BasicServicesKit';

@Entry
@Component
struct WebComponent {
  controller: webview.WebviewController = new webview.WebviewController();

  build() {
    Column() {
      Web({ src: $rawfile('index.html'), controller: this.controller })
        .javaScriptAccess(true)
        .onPageEnd(e => {
          try {
            this.controller.runJavaScript('test()')
              .then((result) => {
                console.log('result: ' + result);
              })
              .catch((error: BusinessError) => {
                console.error("error: " + error);
              })
            if (e) {
              console.info('url: ', e.url);
            }
          } catch (error) {
            let e: BusinessError = error as BusinessError;
            console.error(`ErrorCode: ${e.code},  Message: ${e.message}`);
          }
        })
    }
  }
}

加载html文件

TypeScript 复制代码
<!-- index.html -->
<!DOCTYPE html>
<html>
<meta charset="utf-8">
<body>
Hello world!
</body>
<script type="text/javascript">
function test() {
console.log('Ark WebComponent')
return "This value is from index.html"
}
</script>
</html>

案例介绍

在这个案例中抽奖转盘是一个Web页面。我们点击抽奖,Web页面中的抽奖转盘会开始运动,(停顿)结束抽奖后,原生页面会弹出一个提示弹窗。

图2抽奖转盘案例

Web页面准备

Web抽奖应用的本地页面代码在entry\src\main\resources目录下,由index.html、index.js、index.css文件组成。抽奖方法的入口函数为startDraw,定义在index.js文件中,为Web应用。

index.html文件代码如下所示:

TypeScript 复制代码
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" type="text/css" href="./css/index.css">
<meta charset="UTF-8">
<title>抽奖页面</title>
<style>
#prize {
border-radius: 16px 16px 16px 16px;
background-image: linear-gradient(180deg, #A2DAFF 0%, #EAF5FF 100%);
margin-left: 1.82%;
margin-top: 1.43%;
width: 96.5%;
height: 96.7%;
}
</style>
</head>
<body>
<div class="luckyDraw">
<!-- Use an unordered list to implement a lottery tray -->
<ul id="prize" class="prizes">
<li class="prizes-li active"><img class="pic" src="#"></li>
<li class="prizes-li"><img class="pic" src="#"></li>
<li class="prizes-li"><img class="pic" src="#"></li>
<li class="prizes-li"><img class="pic" src="#"></li>
<li class="prizes-li"><img class="pic" src="#"></li>
<li class="prizes-li"><img class="pic" src="#"></li>
<li class="prizes-li"><img class="pic" src="#"></li>
<li class="prizes-li"><img class="pic" src="#"></li>
<li class="prizes-li"><img class="pic" onclick="startDraw()" src="#"></li>
</ul>
</div>
<script src="./js/index.js"></script>
</body>
</html>

index.js关键代码如下所示:

TypeScript 复制代码
// 奖品数组
let prizesArr = ["啤酒", "奶茶", "汉堡", "咖啡", "西瓜", "鸡腿", "柠檬", "蛋糕"];
// 奖品对应的图片数组
let arrBigImg = ["./img/1-beer.png", "./img/2-milk.png", "./img/3-hamburg.png",
"./img/4-coffee.png", "./img/5-watermelon.png", "./img/6-drumstick.png",
"./img/7-lemon.png", "./img/8-cake.png", "./img/9-prizes.png"];
// 省略其他的其他参数
...
// 转盘函数
function roll() {
// 省略实现代码
...
}

function startDraw() {
if (isClick) {
count = 0;
// 随即生成位置
index = Math.floor(Math.random() * prizesArr.length + 1);
roll();
isClick = false;
}
}

function openDialog() {
confirm(prizesArr[prizesPosition]);
}

原生页面

为了实现抽奖功能,在原生页面需要实现的具体步骤如下所示:

  1. 在按钮的点击事件中,通过runJavaScript方法,来调用Web页面中的抽奖方法。
  2. Web页面完成抽奖后,我们要在Web页面中调用confirm方法,提示抽奖完成。
  3. 完成抽奖后,要在原生页面中写一个onConfirm的确认事件。
  4. 在onConfirm确认事件中,调用AlertDialog方法,来实现二次确认弹窗, 用于用户的友好交互。

ArkTS关键代码如下所示:

TypeScript 复制代码
import { webview } from '@kit.ArkWeb';
import { router } from '@kit.ArkUI';

@Entry
@Component
struct WebPage {
// 创建WebviewController对象
webController: webview.WebviewController = new webview.WebviewController();
build() {
Stack({ alignContent: Alignment.TopStart }) {
...
Row() {
Column() {
Row() {
...
// Web组件,src为资源地址,controller为控制器
Web({ src: this.params['path'], controller: this.webController })
.zoomAccess(false)
.width(Const.WebConstant_WIDTH)
.aspectRatio(1)
// 网页调用confirm()告警时触发此回调
.onConfirm((event) => {
// 用户定义的弹窗
AlertDialog.show({
message: Const.WEB_ALERT_DIALOG_TEXT_VALUE + event?.message,
confirm: {
value: $r('app.string.web_alert_dialog_button_value'),
action: () => {
event?.result.handleConfirm();
}
},
cancel: () => {
event?.result.handleCancel();
}
});
return true;
})
...
// 抽奖按钮
Button($r('app.string.btnValue'))
.fontSize(Const.WebConstant_BUTTON_FONT_SIZE)
.fontColor($r('app.color.start_window_background'))
.margin({ top: Const.WebConstant_BUTTON_MARGIN_TOP })
.width(Const.WebConstant_BUTTON_WIDTH)
.height(Const.WebConstant_BUTTON_HEIGHT)
.backgroundColor($r('app.color.blue'))
.borderRadius(Const.WebConstant_BUTTON_BORDER_RADIUS)
.onClick(() => {
// 调用js函数的入口
this.webController.runJavaScript('startDraw()');
})
}
.width(Const.WebConstant_FULL_WIDTH)
.height(Const.WebConstant_FULL_HEIGHT)
}
...
}
}
相关推荐
航Hang*16 分钟前
前端项目2-01:个人简介页面
前端·经验分享·html·css3·html5·webstorm
MaisieKim_29 分钟前
python与nodejs哪个性能高
前端·python·node.js
水煮白菜王1 小时前
深入理解 Webpack 核心机制与编译流程
前端·webpack·node.js
梦幻通灵1 小时前
Excel分组计算求和的两种实现方案
前端·excel
bestadc1 小时前
鸿蒙 UIAbility组件与UI的数据同步和窗口关闭
harmonyos
whatever who cares2 小时前
CSS3 伪类和使用场景
前端·css·css3
水银嘻嘻2 小时前
Web 自动化之 HTML & JavaScript 详解
前端·自动化·html
天天打码2 小时前
Lynx-字节跳动跨平台框架多端兼容Android, iOS, Web 原生渲染
android·前端·javascript·ios
枫叶丹42 小时前
【HarmonyOS Next之旅】DevEco Studio使用指南(二十二)
华为·harmonyos·deveco studio·harmonyos next
大G哥2 小时前
项目中利用webpack的require.context实现批量引入/导入图片
前端·webpack·node.js