鸿蒙Web组件的生命周期是什么(新手必看)
我们可以使用 Web 组件加载本地或者在线网页。Web 组件提供了丰富的组件生命周期回调接口,通过这些回调接口,开发者可以感知 Web 组件的生命周期状态变化,并进行相关的业务处理。
Web 组件的状态主要包括:将 Controller(控制器)绑定到 Web 组件、网页加载开始、网页加载进度、网页加载结束、页面即将可见等。Web 组件的生命周期示意图如下图所示:

图 1 Web组件的生命周期示意图
在回调中,可以使用如 loadUrl、getWebId 等与网页本身无关的接口。然而,由于此时网页尚未加载完成,因此无法在回调中使用涉及网页操作的接口,如 zoomIn、zoomOut 等。
在多 frame 页面中,多个 frame 有可能同时开始加载,因此有可能出现主 frame 已经加载完成而子 frame 才开始加载或者仍在加载的情况。此外,同一页面的导航(如片段导航、历史状态切换等),或者在提交前失败、被取消的导航等,也不会触发该回调。
需要注意的是,收到该回调并不能保证 Web 绘制的下一帧将反映此时 DOM 的状态。
具体来说,在加载 LoadUrl 和 iframe 时,onLoadIntercept 事件会正常回调,但 onOverrideUrlLoading 事件在加载 LoadUrl 时不会触发,在 iframe 加载 HTTP(s) 协议或 about:blank 时也不会触发。
下面通过一个示例,来更好地认识 ArkWeb 组件的回调函数,示例代码如下:

图 2 ArkWeb 组件事件回调演示
Web 组件提供了如下接口来进行通知:
Web 组件的状态主要包括:将 Controller(控制器)绑定到 Web 组件、网页加载开始、网页加载进度、网页加载结束、页面即将可见等。Web 组件的生命周期示意图如下图所示:

图 1 Web组件的生命周期示意图
1) onControllerAttached事件
当 Controller 成功绑定到 Web 组件时,会触发该回调,并且禁止在该事件回调之前调用与 Web 组件相关的接口,否则会抛出 js-error 异常。建议在此回调中注入 JavaScript 对象 registerJavaScriptProxy,并设置自定义用户代理 setCustomUserAgent。在回调中,可以使用如 loadUrl、getWebId 等与网页本身无关的接口。然而,由于此时网页尚未加载完成,因此无法在回调中使用涉及网页操作的接口,如 zoomIn、zoomOut 等。
2) onLoadIntercept事件
在 Web 组件加载 URL 之前触发该回调,用于判断是否阻止此次访问。默认允许加载。3) onInterceptRequest事件
在 Web 组件加载 URL 之前触发该回调,用于拦截 URL 并返回响应数据。4) onPageBegin事件
在网页开始加载时触发该回调,并且只在主 frame(框架,表示一个 HTML 元素,用于展示 HTML 页面的 HTML 元素)中触发。如果加载的是 iframe 或者 frameset(用于包含 frame 的 HTML 标签)的内容,则不会触发此回调。在多 frame 页面中,多个 frame 有可能同时开始加载,因此有可能出现主 frame 已经加载完成而子 frame 才开始加载或者仍在加载的情况。此外,同一页面的导航(如片段导航、历史状态切换等),或者在提交前失败、被取消的导航等,也不会触发该回调。
5) onProgressChange事件
用于获取当前页面加载的进度。在多 frame 页面中,子 frame 有可能还在继续加载,而主 frame 已经加载完成。因此,在触发 onPageEnd 事件后,依然有可能收到 onProgressChange 事件。6) onPageEnd事件
网页加载完成时触发该回调,且只在主 frame 上触发。多 frame 页面有可能同时开始加载,即使主 frame 已经加载结束,子 frame 也有可能才开始或者继续加载中。同一页面的导航(如片段导航、历史状态切换等),或者在提交前失败、被取消的导航等,也不会触发该回调。推荐在此回调中执行 JavaScript 脚本,如 loadUrl 等。需要注意的是,收到该回调并不能保证 Web 绘制的下一帧将反映此时 DOM 的状态。
Web组件加载的其他事件
1) aboutToAppear事件
aboutToAppear 事件在创建自定义组件的新实例后,在执行其 build 函数前执行。一般建议在此设置 WebDebug 调试模式 setWebDebuggingAccess,设置 Web 内核自定义协议 URL 的跨域请求与 fetch 请求的权限 customizeSchemes,设置 Cookie(configCookie) 等。2) onOverrideUrlLoading事件
当 URL 将要加载到当前 Web 中时,onOverrideUrlLoading 事件让宿主应用程序有机会获得控制权。回调函数返回 true 会使当前 Web 中止加载 URL,返回 false 会使 Web 继续照常加载 URL。onLoadIntercept 接口和 onOverrideUrlLoading 接口行为不一致,触发时机也不同,所以它们在应用场景上存在一定区别。具体来说,在加载 LoadUrl 和 iframe 时,onLoadIntercept 事件会正常回调,但 onOverrideUrlLoading 事件在加载 LoadUrl 时不会触发,在 iframe 加载 HTTP(s) 协议或 about:blank 时也不会触发。
3) onPageVisible事件
onPageVisible 事件是 Web 回调事件。在渲染流程中,当 HTML 响应的主体开始加载,新页面即将可见时触发该回调。此时文档加载还处于早期,因此链接的资源(比如在线 CSS、在线图片等)可能尚不可用。4) onRenderExited事件
应用渲染进程异常退出时触发该回调,在此回调中可以进行系统资源的释放、数据的保存等操作。如果应用希望进行异常恢复,则需要调用 loadUrl 接口重新加载页面。5) onDisAppear事件
onDisAppear 事件为通用事件,当组件从组件树上卸载时触发该事件。下面通过一个示例,来更好地认识 ArkWeb 组件的回调函数,示例代码如下:
<!-- demo.ets -->
// 导入 ArkWeb 组件
import { webview } from '@kit.ArkWeb';
// 导入业务异常
import { BusinessError } from '@kit.BasicServicesKit';
// 导入弹出窗
import { promptAction } from '@kit.ArkUI';
@Entry
@Component
struct Demo0201 {
/* ========= Web 相关对象 ========= */
// 创建 Web 控制器对象
controller: webview.WebviewController = new webview.WebviewController();
// 创建 Web 响应对象
responseWeb: WebResourceResponse = new WebResourceResponse();
// 创建请求消息头数组
heads: Header[] = new Array();
// 准备一段本地 HTML 内容,用于拦截请求时返回
@State webData: string =
"<!DOCTYPE html>\n" +
"<html>\n" +
"<head>\n" +
"<title>HarmonyOS 开发之路</title>\n" +
"</head>\n" +
"<body>\n" +
"<h1>欢迎进入 HarmonyOS 开发殿堂</h1>\n" +
"</body>\n" +
"</html>";
/* ========= 生命周期 ========= */
aboutToAppear(): void {
// 开启 Web 调试
try {
webview.WebviewController.setWebDebuggingAccess(true);
console.log('aboutToAppear 执行了');
} catch (error) {
console.error(
`错误码:${(error as BusinessError).code}, 错误信息:${(error as BusinessError).message}`
);
}
}
/* ========= UI 构建 ========= */
build() {
Column() {
Web({
src: $rawfile('demo0201.html'), // 加载本地 html 文件
controller: this.controller
})
// 控制器挂载完成(推荐在此 loadUrl、注入 JS 对象等)
.onControllerAttached(() => {
console.log('onControllerAttached 方法执行');
})
// 拦截即将加载的 URL,返回 true 阻止加载
.onLoadIntercept((event) => {
if (event) {
console.log('onLoadIntercept 执行了:' + event.data.getRequestUrl());
}
// 返回 true 表示阻止此次加载,否则允许
return true;
})
// 覆盖 URL 加载策略
.onOverrideUrlLoading((webResourceRequest: WebResourceRequest) => {
if (
webResourceRequest &&
webResourceRequest.getRequestUrl() === 'about:blank'
) {
return true;
}
return false;
})
// 拦截资源请求(可返回自定义响应)
.onInterceptRequest((event) => {
if (event) {
console.log('onInterceptRequest 执行了:' + event.request.getRequestUrl());
// 构造响应头
this.heads.push({
headerKey: 'Connection',
headerValue: 'keep-alive'
});
// 填充自定义响应
this.responseWeb.setResponseHeader(this.heads);
this.responseWeb.setResponseData(this.webData);
this.responseWeb.setResponseEncoding('utf-8');
this.responseWeb.setResponseMimeType('text/html');
this.responseWeb.setResponseCode(200);
this.responseWeb.setReasonMessage('Ok');
// 返回响应对象;返回 null 则按默认方式加载
return this.responseWeb;
}
return null;
})
// 页面开始加载
.onPageBegin((event) => {
if (event) {
console.log('onPageBegin 执行:' + event.url);
}
})
// 首次内容绘制完成
.onFirstContentfulPaint((event) => {
if (event) {
console.log('onFirstContentfulPaint 执行:' + event.firstContentfulPaintMs);
}
})
// 加载进度变化
.onProgressChange((event) => {
if (event) {
console.log('onProgressChange 执行:' + event.newProgress);
}
})
// 页面加载结束(推荐在此执行 JS 脚本)
.onPageEnd((event) => {
if (event) {
console.log('onPageEnd 执行:' + event.url);
}
})
// 页面可见
.onPageVisible((event) => {
console.log('onPageVisible 执行:' + event.url);
})
// 渲染进程退出
.onRenderExited((event) => {
if (event) {
console.log('onRenderExited 执行');
}
})
// Web 组件消失
.onDisAppear(() => {
promptAction.showToast({
message: 'Web 组件隐藏啦',
duration: 2000
});
});
}
}
}
<!-- demo.html -->
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
</head>
<body>
<h1>Hello, ArkWeb</h1>
</body>
</html>
运行效果如下图所示:
图 2 ArkWeb 组件事件回调演示
Web组件性能指标
在网页加载过程中,需要关注一些重要的性能指标,例如 FCP(First Contentful Paint,首次内容绘制)、FMP(First Meaningful Paint,首次有效绘制)、LCP(Largest Contentful Paint,最大内容绘制)等。Web 组件提供了如下接口来进行通知:
- onFirstContentfulPaint 事件:网页首次内容绘制的回调函数。在首次绘制文本、图像、非空白 Canvas 或者 SVG 时触发;
- onFirstMeaningfulPaint 事件:网页首次有效绘制的回调函数。在首次绘制页面主要内容时触发;
- onLargestContentfulPaint 事件:网页绘制页面最大内容的回调函数。可视区域内容最大的可见元素开始出现在页面时触发。
ICP备案:
公安联网备案: