相信大家都遇到过这样的场景,有时候我们点击应用的页面,会跳转到一个类似浏览器加载的页面,加载完成后,才显示这个页面的具体内容,这个加载和显示网页的过程通常都是浏览器的任务。
ArkUI 为我们提供了 Web 组件来加载网页,借助它我们就相当于在自己的应用程序里嵌入一个浏览器,从而非常轻松地展示各种各样的网页。
本文将为您介绍 Web 组件一些常用 API 的使用。
Web 组件的使用非常简单,只需要在 Page 目录下的 ArkTS 文件中创建一个 Web 组件,传入两个参数就可以了。其中 src 指定引用的网页路径,controller 为组件的控制器,通过 controller 绑定 Web 组件,用于实现对 Web 组件的控制。
// xxx.ets
@Entry
@Component
struct WebComponent {
controller: WebController = new WebController();
build() {
Column() {
Web({ src: 'https://developer.harmonyos.com/', controller: this.controller })
}
}
}
代码运行效果图如下:
访问在线网页时您需要在 module.json5 文件中申明网络访问权限:ohos.permission.INTERNET。
{
"module" : {
"requestPermissions":[
{
"name": "ohos.permission.INTERNET"
}
]
}
}
前面实现了 Web 组件加载在线网页,Web 组件同样也可以加载本地网页。首先在 main/resources/rawfile 目录下创建一个 HTML 文件,然后通过$rawfile 引用本地网页资源,示例代码如下:
// xxx.ets
@Entry
@Component
struct SecondPage {
controller: WebController = new WebController();
build() {
Column() {
Web({ src: $rawfile('index.html'), controller: this.controller })
}
}
}
// xxx.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
</head>
<body>
<img src="pad.jpg">
</body>
</html>
代码运行效果图如下:
为了方便开发者学习,后面用到的 HTML 都是以文件的形式放到 rawfile 目录下,加载本地网页。
有的网页可能不能很好适配手机屏幕,需要对其缩放才能有更好的效果,开发者可以根据需要给 Web 组件设置 zoomAccess 属性,zoomAccess 用于设置是否支持手势进行缩放,默认允许执行缩放。Web 组件默认支持手势进行缩放。
Web({ src:'www.example.com', controller:this.controller })
.zoomAccess(true)
您还可以使用 zoom(factor: number) 方法用于设置网站的缩放比例。其中 factor 表示缩放倍数,下面示例,当点击一次按钮时,页面放大为原来的 1.5 倍。
// xxx.ets
@Entry
@Component
struct WebComponent {
controller: WebController = new WebController();
factor: number = 1.5;
build() {
Column() {
Button('zoom')
.onClick(() => {
this.controller.zoom(this.factor);
})
Web({ src: 'www.example.com', controller: this.controller })
}
}
}
需要注意的是只有网页自身支持缩放,才能在 Web 组件里面进行缩放。
如果需要对文本进行缩放,可以使用 textZoomAtio(textZoomAtio: number) 方法。其中 textZoomAtio 用于设置页面的文本缩放百分比,默认值为 100,表示 100%,以下示例代码将文本放大为原来的 1.5 倍。
Web({ src:'www.example.com', controller:this.controller })
.textZoomAtio(150)
效果图如下:
从上面的效果图可以看出使用 textZoomAtio,文本会放大,但是图片不会随着文本一起放大。
Web 组件还提供了处理 Javascript 的对话框、网页加载进度及各种通知与请求事件的方法。例如 onProgressChange 可以监听网页的加载进度,onPageEnd 在网页加载完成时触发该回调,且只在主 frame 触发,onConfirm 则在网页触发 confirm 告警弹窗时触发回调。下面以 onConfirm 事件为例讲解 Web 组件事件的使用,更多 Web 组件事件可以查看事件。
如果您希望响应 Web 组件中网页的警告弹窗事件,您可以在 onAlert 或者 onConfirm 的回调方法中处理这些事件。以 confirm 弹窗为例,在网页触发 onConfirm() 告警弹窗时,显示一个 AlertDialog 弹窗。
// xxx.ets
@Entry
@Component
struct WebComponent {
controller:WebController = new WebController();
build() {
Column() {
Web({ src:$rawfile('index.html'), controller:this.controller })
.onConfirm((event) => {
AlertDialog.show({
title: 'title',
message: event.message,
confirm: {
value: 'onAlert',
action: () => {
event.result.handleConfirm();
}
},
cancel: () => {
event.result.handleCancel();
}
})
return true;
})
}
}
}
当 onConfirm 回调返回 false 时,触发默认弹窗。当回调返回 true 时,系统应用可以调用系统弹窗能力(包括确认和取消),并且需要根据用户的确认或取消操作调用 JsResult 通知 Web 组件。
在 rawfile 目录下创建如下 HTML 文件:
<!-- index.html -->
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
</head>
<body>
</body>
<script type="text/javascript">
confirm("confirm message from html")
</script>
</html>
效果图如下:
在开发专为适配 Web 组件的网页时,您可以实现 Web 组件和 JavaScript 代码之间的交互。Web 组件可以调用 JavaScript 方法,JavaScript 也可以调用 Web 组件里面的方法。
如果您希望加载的网页在 Web 组件中运行 JavaScript,则必须为您的 Web 组件启用 JavaScript 功能,默认情况下是允许 JavaScript 执行的。
Web({ src:'https://www.example.com', controller:this.controller })
.javaScriptAccess(true)
您可以在 Web 组件 onPageEnd 事件中添加 runJavaScript 方法。事件是网页加载完成时的回调,runJavaScript 方法可以执行 HTML 中的 JavaScript 脚本。
// xxx.ets
@Entry
@Component
struct WebComponent {
controller: WebController = new WebController();
@State webResult: string = ''
build() {
Column() {
Text(this.webResult).fontSize(20)
Web({ src: $rawfile('index.html'), controller: this.controller })
.javaScriptAccess(true)
.onPageEnd(e => {
this.controller.runJavaScript({
script: 'test()',
callback: (result: string)=> {
this.webResult = result;
}});
})
}
}
}
<!-- index.html -->
<!DOCTYPE html>
<html>
<meta charset="utf-8">
<body>
</body>
<script type="text/javascript">
function test() {
return "This value is from index.html"
}
</script>
</html>
当页面加载完成时,触发 onPageEnd 事件,调用 HTML 文件中的 test 方法并将结果返回给 Web 组件。
您可以使用 registerJavaScriptProxy 将 Web 组件中的 JavaScript 对象注入 daowindow 对象中,这样网页中的 JS 就可以直接调用该对象了。需要注意的是,要想 registerJavaScriptProxy 方法生效,须调用 refresh 方法。下面的示例将 ets 文件中的对象 testObj 注入到了 window 对象中。
// xxx.ets
@Entry
@Component
struct WebComponent{
@State dataFromHtml: string = ''
controller: WebController = new WebController()
testObj = {
test: (data) => {
this.dataFromHtml = data;
return 'ArkUI Web Component';
},
toString: () => {
console.log('Web Component toString');
}
}
build() {
Column() {
Text(this.dataFromHtml).fontSize(20)
Row() {
Button('Register JavaScript To Window').onClick(() => {
this.controller.registerJavaScriptProxy({
object: this.testObj,
name: 'objName',
methodList: ['test', 'toString'],
});
this.controller.refresh();
})
}
Web({ src: $rawfile('index.html'), controller: this.controller })
.javaScriptAccess(true)
}
}
}
其中 object 表示参与注册的对象,name 表示注册对象的名称为 objName,与 window 中调用的对象名一致;methodList 表示参与注册的应用侧 JavaScript 对象的方法,包含 test、toString 两个方法。在 HTML 中使用的时候直接使用 objName 调用 methodList 里面对应的方法即可,示例如下:
// index.html
<!DOCTYPE html>
<html>
<meta charset="utf-8">
<body>
<button onclick="htmlTest()">调用 Web 组件里面的方法</button>
</body>
<script type="text/javascript">
function htmlTest() {
str = objName.test("param from Html");
}
</script>
</html>
您还可以使用 deleteJavaScriptRegister 删除通过 registerJavaScriptProxy 注册到 window 上的指定 name 的应用侧 JavaScript 对象。
当我们在使用浏览器浏览网页时,可以执行返回、前进、刷新等操作,Web 组件同样支持这些操作。您可以使用 backward() 返回到上一个页面,使用 forward() 前进一个页面,您也可以使用 refresh() 刷新页面,使用 clearHistory() 来清除历史记录。下面通过一个简单的”浏览器”示例呈现这些功能。
// xxx.ets
@Entry
@Component
struct Page5 {
controller: WebController = new WebController();
build() {
Column() {
Row() {
Button("前进").onClick(() => {
this.controller.forward();
})
Button("后退").onClick(() => {
this.controller.backward();
})
Button("刷新").onClick(() => {
this.controller.refresh();
})
Button("停止").onClick(() => {
this.controller.stop();
})
Button("清除历史").onClick(() => {
this.controller.clearHistory();
})
}
.padding(12)
.backgroundColor(Color.Gray)
.width('100%')
Web({ src: 'https://developer.harmonyos.com/', controller: this.controller })
}
.height('100%')
}
}
您可以使用 accessBackward() 来检查当前页面是否有后退来时记录,如果有则该方法返回 true。同样,您可以使用 accessForward() 来检查是否存在前进历史记录。
您可以使用 onConsole 获取网页输出的调试日志信息,当你在你的网页中使用 console 打印日志时,HarmonyOS 系统都会调用相应的 onConsole 方法,这样你就可以获取到网页日志信息了。下面展示了如何在 Web 组件中使用 onConsole 输出网页中的日志:
// xxx.ets
@Entry
@Component
struct WebComponent {
controller: WebController = new WebController();
build() {
Column() {
Web({ src: $rawfile('index.html'), controller: this.controller })
.onConsole((event) => {
console.log('getMessage:' + event.message.getMessage());
console.log('getMessageLevel:' + event.message.getMessageLevel());
return false;
})
}
}
}
// index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
</head>
<body>
</body>
<script type="text/javascript">
console.info('info message');
console.error('error message');
</script>
</html>
event 的内容为 ConsoleMessage,它包括一个对象来表示正在传递的日志信息的 MessageLevel 类型。您可以使用 getMessageLevel() 查询消息级别以确定消息的严重性,然后根据自身业务采取相应的操作。上面的示例代码,会打印如下所示的 日志消息:
08-27 19:47:27.476 27869-27937/com.example.webtest D 03B00/JSApp: app Log: getMessage:info message
08-27 19:47:27.476 27869-27937/com.example.webtest D 03B00/JSApp: app Log: getMessageLevel:3
08-27 19:47:27.478 27869-27937/com.example.webtest D 03B00/JSApp: app Log: getMessage:error message
08-27 19:47:27.478 27869-27937/com.example.webtest D 03B00/JSApp: app Log: getMessageLevel:1
本篇 Codelab 是基于 ArkTS 的声明式开发范式的样例,主要介绍了 Web 组件如何加载本地和云端 H5 小程序。
访问在线网页时需添加网络权限:ohos.permission.INTERNET。
在公众号「Android指南」后台回复关键字「Web抽奖」即可获取。