鸿蒙PC实战_HarmonyOS + Cordova:从原生到 index.html 渲染的全流程
·
全流程总览(Flowchart)
渲染错误: Mermaid 渲染失败: Parse error on line 6: ...rdova 解析 preferences(Hostname 等)] F - -----------------------^ Expecting 'SQE', 'DOUBLECIRCLEEND', 'PE', '-)', 'STADIUMEND', 'SUBROUTINEEND', 'PIPE', 'CYLINDEREND', 'DIAMOND_STOP', 'TAGEND', 'TRAPEND', 'INVTRAPEND', 'UNICODE_TEXT', 'TEXT', 'TAGSTART', got 'PS'
代码驱动解读(主线)
启动入口:EntryAbility 初始化 Web 引擎并加载页面
// entry/src/main/ets/entryability/EntryAbility.ets
import { AbilityConstant, UIAbility, Want } from '@kit.AbilityKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
import { window } from '@kit.ArkUI';
import { webview } from '@kit.ArkWeb';
import { ConfigurationConstant } from '@kit.AbilityKit';
export default class EntryAbility extends UIAbility {
onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
// ...(省略 ColorMode 设置与日志)
webview.WebviewController.initializeWebEngine();
}
onWindowStageCreate(windowStage: window.WindowStage): void {
windowStage.loadContent('pages/Index', (err) => {
if (err.code) {
// 错误处理 ...
return;
}
// 加载成功日志 ...
});
}
}
要点:
- initializeWebEngine 在 Ability 创建时初始化 ArkWeb 内核。
- loadContent(‘pages/Index’) 切入 UI 层
Index页面。
代码说明:
EntryAbility是应用的 UIAbility 入口,负责 ArkWeb 内核的一次性初始化与页面装载。onCreate中调用initializeWebEngine(),确保后续 ArkUIWeb组件可用。onWindowStageCreate通过windowStage.loadContent('pages/Index')切换到 ArkUI 首屏页面;发生异常时提前返回避免空白页。
ArkUI 页面:Index 作为 MainPage 的父组件,负责生命周期透传
// entry/src/main/ets/pages/Index.ets
import {
MainPage,
pageBackPress,
pageHideEvent,
pageShowEvent,
PluginEntry
} from '@magongshou/harmony-cordova/Index';
@Entry
@Component
struct Index {
cordovaPlugs: Array<PluginEntry> = [];
onPageShow() { pageShowEvent(); }
onBackPress() { pageBackPress(); return true; }
onPageHide() { pageHideEvent(); }
build() {
RelativeContainer() {
MainPage({
isWebDebug: false,
cordovaPlugs: this.cordovaPlugs
});
}
.height('100%')
.width('100%')
}
}
要点:
- 父组件把 页面生命周期 与 返回键 事件传递给 Cordova
- 渲染
MainPage,承载 WebView 与 Cordova 初始化。
代码说明:
Index仅负责承载MainPage与透传生命周期,不直接操控 Web 内核。onPageShow/onPageHide/onBackPress分别映射为 Cordova 的resume/pause/backbutton事件。return true表示拦截系统返回键,由 Cordova(Web 层)决定导航与退出策略。MainPage参数中可注入 ArkTS 插件列表cordovaPlugs,用于扩展原生能力。
MainPage:初始化 Cordova,计算默认入口并驱动 Web 载入
// cordova/src/main/ets/components/MainPage.ets(片段)
@Component
export struct MainPage {
private webTag: string = 'scheme-handler' + '-' + util.generateRandomUUID(false);
private strTmpUrl:string = 'www.example.com';
private src:string = 'https://' + this.strTmpUrl + '/index.html';
// ... 省略属性
aboutToAppear() {
// ... 省略显示监听/Cookie 配置
if (!cordovaWebIdToWebviewGlobe.hasKey(this.webTag)) {
webview.WebviewController.setWebDebuggingAccess(this.isWebDebug);
cordova.SetSchemeHandler(this.customSchemes, this.webTag);
cordova.RegisterCustomSchemes(this.customSchemes);
let preferences:string = cordova.InitCordova(
this.webTag,
this.strTmpUrl,
PluginHandler,
getContext(this).databaseDir,
getContext(this).resourceManager,
this.customHttpHeaders,
this.isAllowCredentials
);
let jsonConfig:object = JSON.parse(preferences) as object;
let arrayObject:Array<object> = jsonConfig?.['preferences'];
arrayObject.forEach((obj:object)=>{
if(obj?.['name'] && obj?.['value']) {
if(obj?.['name'] === 'Hostname') {
this.strTmpUrl = obj?.['value']; // 设置 Hostname
}
// ... 省略 Splash 参数解析
this.cordovaPreferences.set(obj?.['name'], obj?.['value']);
}
})
if (this.indexPage == '') { // 默认加载页面
this.src = 'https://' + this.strTmpUrl + '/www/index.html';
} else {
// ... 省略自定义入口逻辑
}
InitArkTsPlugins(this.webId, this.webTag, this.cordovaPreferences, this.cordovaInterface, this.cordovaWebView, this.cordovaPlugs);
// ... 省略生命周期设置与闪屏
}
this.cordovaWebView.setIsShow(true);
// ... 通知插件、注册监听
}
@Builder
builder() {
Column() {
Stack({ alignContent: Alignment.Top }) {
Web({ src: this.src, controller: this.webviewController })
.onControllerAttached(() => { /* 省略 */ })
.onLoadIntercept((event) => { /* 省略 */ return false; })
.onOverrideUrlLoading((req) => { return this.lifeCycle.execOnOverrideUrlLoading(req, this.parentPage); })
.onInterceptRequest((event) => { /* 省略 */ return null; })
.onPageBegin((event) => { /* 省略 */ })
.onProgressChange((event) => { /* 省略 */ })
.javaScriptAccess(true)
// ... 省略若干能力开关
.onPageEnd((event) => {
this.title = this.webviewController.getTitle();
this.cordovaWebView.setWebAttribute(this.webAttributeModifier.attribute);
this.webviewController.setDownloadDelegate(this.downDelegate);
if (this.onSetCordovaWebAttribute) {
this.onSetCordovaWebAttribute(this.cordovaWebView);
}
if (event) {
this.lifeCycle.execOnPageEnd(event.url, this.webviewController, this.parentPage);
}
this.splashScreenHide();
})
.onPrompt((event) => {
// cordova 依赖此函数进行 JS 桥接(必须调用)
let ret = cordova.onJsPrompt(this.webTag, event.url, event.message, event.value);
if (ret !== undefined && ret != '') {
event.result.handlePromptConfirm(ret);
return false;
} else if (ret === undefined) {
// ... 省略弹窗回退逻辑
return true;
}
return false;
})
// ... 省略地理位置、原生嵌入等
.height('100%')
.width('100%')
}
.height('100%')
.width('100%')
}
.height('100%')
.width('100%')
.backgroundColor('#000000')
}
}
要点:
InitCordova返回的preferences中可设定Hostname,默认入口拼为https://{Hostname}/www/index.html。SetSchemeHandler/RegisterCustomSchemes配合 Cordova 原生资源路由,拦截并映射到rawfile资源包。- ArkUI
Web组件接收src并最终调用loadUrl加载页面,onPageEnd隐藏闪屏。
代码说明:
aboutToAppear的初始化保证每个webTag仅初始化一次,兼容多 WebView 场景。InitCordova读取preferences并设置Hostname;若未指定indexPage则默认使用/www/index.html。SetSchemeHandler/RegisterCustomSchemes建立自定义协议到rawfile的映射,确保本地打包资源可被 Web 访问。- ArkUI
Web通过Web({ src, controller })载入页面;onPrompt驱动 Cordova JS 桥;onPageEnd同步标题/下载代理/属性并隐藏闪屏。
JS 桥与页面事件:Index 透传 -> cordova.onArkTsResult
// cordova/Index.ets(片段)
import cordova from 'libcordova.so'
import { ArkTsAttribute } from './src/main/ets/components/PluginGlobal';
export function pageShowEvent() {
let result: ArkTsAttribute = {content: 'resume', result: []};
cordova.onArkTsResult(JSON.stringify(result), 'CoreHarmony', '');
}
export function pageHideEvent() {
let result: ArkTsAttribute = {content: 'pendingPause', result: []};
cordova.onArkTsResult(JSON.stringify(result), 'CoreHarmony', '');
}
export function pageBackPress() {
let result: ArkTsAttribute = {content: 'overrideBackbutton', result: []};
cordova.onArkTsResult(JSON.stringify(result), 'CoreHarmony', '');
}
要点:
- ArkTS 侧通过
onArkTsResult将页面生命周期与返回键事件分发到 Cordova/JS 层,触发backbutton、pause/resume等回调。
代码说明:
- 三个方法把 ArkTS 生命周期/按键事件封装为
ArkTsAttribute,经cordova.onArkTsResult发送到 JS 层。 - JS 侧触发 Cordova 标准事件:
pause、resume、backbutton,插件可据此处理状态与导航。 - 保证 ArkTS 页面与 Web 应用生命周期一致,避免前后台状态错乱。
最终入口:rawfile/www/index.html(游戏首页)
<!-- cordova/src/main/resources/rawfile/www/index.html(片段) -->
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>2048</title>
<link rel="stylesheet" href="css/style.css" />
</head>
<body>
<div class="wrap">
<div class="head">
<h1>2048</h1>
<div class="stats">
<div class="badge"><small>分数</small><b id="score">0</b></div>
<div class="badge"><small>最佳</small><b id="best">0</b></div>
</div>
</div>
<div class="toolbar">
<button id="newGame">新游戏</button>
<span class="tip">使用键盘方向键(↑↓←→)进行移动。</span>
</div>
<div class="board">
<div id="grid" class="grid"></div>
</div>
</div>
<script src="js/app.js"></script>
</body>
</html>
要点:
- 资源路径以
www/为根,结合Hostname的自定义协议,由 Cordova 原生资源处理器映射到rawfile。
代码说明:
- 页面结构包含标题、分数统计与棋盘容器
#grid;js/app.js为游戏逻辑入口。 - 静态资源路径相对
www/根,打包后通过原生资源处理器映射为rawfile/www/...。 - 在鸿蒙 PC 端,键盘交互(方向键/WASD)由 Web 层处理,可与触控手势共存。
加载过程时序(Sequence Diagram)
小结
- 原生入口
EntryAbility初始化 Web 引擎,加载pages/Index。 Index作为父组件,渲染MainPage并上报生命周期/返回键至 Cordova。MainPage完成 Cordova 初始化,解析Hostname,默认拼接https://{Hostname}/www/index.html。- ArkUI
Web组件加载 URL,onPageEnd隐藏闪屏,最终渲染index.html游戏页面。
欢迎加入开源鸿蒙PC社区:https://harmonypc.csdn.net/
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)