ArkWeb简介:
(1)概念介绍: Web组件用于在应用程序中显示Web页面内容,为开发者提供页面加载、页面交互、页面调试等能力。可以用于实现移动端的混合式开发(Hybrid App ):
- 页面加载:Web组件提供了基础的前端页面加载的能力,包括加载网络页面、本地页面以及html格式文本数据。
- 页面交互:Web组件提供丰富的页面交互的方式,包括:应用侧使用前端页面JavaScript等能力,设置前端页面深色模式,新窗口中加载页面,位置权限管理,Cookie管理。
- 页面调试:Web组件支持使用Devtools工具调试前端页面
(2)ArkWebAPI参考
Web组件:提供具有网页显示能力的一种组件。
Webview:提供web控制能力的相关接口。
(3)Web组件的生命周期
Web页面加载与显示
- 加载网络页面
- 开发者可以在Web组件创建时,指定默认加载的网络页面。在默认页面加载完成后,如果开发者需要变更此Web组件显示的网络页面,可以通过调用loadUrl()接口加载指定的网页。
@Entry @Component
struct WebComponent {
webviewController: web_webview.WebviewController = new web_webview.WebviewController();
build() {
Column() {
Button('loadUrl').onClick(() => {
try { // 点击按钮时,通过loadUrl,跳转到www.example1.com
this.webviewController.loadUrl('www.example1.com');
} catch (error) { ... } })
// 组件创建时,加载www.example.com
Web({ src: 'www.example.com', controller: this.webviewController})
}
}
}
- 加载本地页面
- 将本地页面文件放在应用的rawfile目录下,开发者可以在Web组件创建的时候指定默认加载的本地页面,并且加载完成后可通过调用loadUrl()接口变更当前Web组件的页面。
import web_webview from '@ohos.web.webview';
import business_error from '@ohos.base';
@Entry
@Component
struct WebComponent {
webviewController: web_webview.WebviewController = new web_webview.WebviewController();
build() {
Column() {
Button('loadUrl')
.onClick(() => {
try {
// 点击按钮时,通过loadUrl,跳转到local1.html
this.webviewController.loadUrl($rawfile("local1.html"));
} catch (error) {
...
}
})
// 组件创建时,通过$rawfile加载本地文件local.html
Web({ src: $rawfile("local.html"), controller: this.webviewController })
}
}
}
- 加载HTML格式数据
@Entry
@Component
struct WebComponent {
controller: web_webview.WebviewController = new web_webview.WebviewController();
build() {
Column() {
Button('loadData')
.onClick(() => {
try {
// 点击按钮时,通过loadData,加载HTML格式的文本数据
this.controller.loadData(
"<html><body bgcolor="white">Source:<pre>source</pre></body></html>",
"text/html",
"UTF-8"
);
} catch (error) {
// …
}
})
// 组件创建时,加载www.example.com
Web({ src: 'www.example.com', controller: this.controller })
}
}
}
应用侧与前端页面交互
- 应用侧调用前端页面函数 应用侧可以通过runJavaScript()方法调用前端页面的JavaScript相关函数。
前端页面代码
<!-- index.html -->
<!DOCTYPE html>
<html>
<body>
<script>
function htmlTest() {
console.info('JavaScript Hello World! ');
}
</script>
</body>
</html>
应用侧代码
import web_webview from '@ohos.web.webview';
@Entry
@Component
struct WebComponent {
webviewController: web_webview.WebviewController
= new web_webview.WebviewController();
build() {
Column() {
Button('runJavaScript')
.onClick(() => {
this.webviewController.runJavaScript('htmlTest()');
})
Web({ src: $rawfile('index.html'), controller: this.webviewController})
}
}
}
- 前端页面调用应用侧函数
使用Web组件将应用侧代码注册到前端页面中,注册完成之后,前端页面中使用注册的对象名称就可以调用应用侧的函数, 实现在前端页面中调用应用侧方法。
注册应用侧代码有两种方式:
-
在Web组件初始化调用,使用javaScriptProxy()接口。
-
在Web组件初始化完成后调用,使用registerJavaScriptProxy()接口。
函数传参支持复杂类型: -
应用侧和前端页面之间传递Array
-
应用侧和前端页面之间传递不带Function的Dictionary
-
应用侧调用前端页面的Callback
-
应用侧调用前端页面Object里的Function
-
前端页面调用应用侧Object里的Function
-
支持Promise场景
前端页面代码
<!-- index.html -->
<!DOCTYPE html>
<html>
<body>
<button type="button" onclick="callArkTS()">Click Me!</button>
<p id="demo"></p>
<script>
function callArkTS() {
let str = testObjName.test();
document.getElementById("demo").innerHTML = str;
console.info('ArkTS Hello World! :' + str);
}
</script>
</body>
</html>
应用侧代码:方法1 javaScriptProxy()
@Entry
@Component
struct WebComponent {
webviewController: web_webview.WebviewController
= new web_webview.WebviewController();
// 声明需要注册的对象
@State testObj: TestClass = new TestClass();
build() {
Column() {
// web组件加载本地index.html页面
Web({ src: $rawfile('index.html'), controller: this.webviewController})
// 将对象注入到web端
.javaScriptProxy({
object: this.testObj,
name: "testObjName",
methodList: ["test"],
controller: this.webviewController
})
}
}
}
方法2 registerJavaScriptProxy()
import web_webview from '@ohos.web.webview';
class TestClass {
constructor() {
}
test(): string {
return 'ArkTS Hello World!';
}
}
class TestClass {
constructor() {
}
test(): string {
return "ArkUI Web Component";
}
toString(): void {
console.log('Web Component toString');
}
}
@State testObj: testClass = new TestClass();
this.webviewController.refresh();
this.webviewController.registerJavaScriptProxy(this.testObj, "testObjName", ["test", "toString"]);
Web({ src: $rawfile('index.html'), controller: this.webviewController })
registerJavaScriptProxy函数传参支持以下复杂类型
- 应用侧和前端页面之间传递Array
test(): Array{
return [1, 2, 3, 4]
}
- 应用侧和前端页面之间传递不带Function的Dictionary
test(): student {
let st: student = {name:"jeck", age:"12"} return st
}
- 应用侧调用前端页面的Callback
test(param: Function): void {
param("call callback");
}
- 应用侧调用前端页面Object里的Function
test(param: ESObject): void {
param.hello("call obj func");
}
- 前端页面调用应用侧Object里的Function
test(): ESObject {
return this.ObjReturn
}
- 支持Promise场景
test(): Promise {
let p: Promise = new Promise(); return p;
}
自定义页面请求响应(响应拦截)
使用场景:Web组件支持在应用拦截到页面请求后自定义响应请求能力。开发者通过 onInterceptRequest() 接口来实现自 定义资源请求响应 。自定义请求能力可以用于开发者自定义Web页面响应、自定义文件资源响应等场景。
Web({ src: $rawfile('index.html'), controller: this.controller })
.onInterceptRequest((event) => {
if (event) {
console.info('url:' + event.request.getRequestUrl());
// 拦截页面请求
if (event.request.getRequestUrl() !== 'https://www.example.com/test.html') {
return null;
}
}
// 构造响应数据
this.responseResource.setResponseData(this.webData);
this.responseResource.setResponseEncoding('utf-8');
this.responseResource.setResponseMimeType('text/html');
this.responseResource.setResponseCode(200);
this.responseResource.setReasonMessage('OK');
return this.responseResource;
})