HarmonyOS 6.1 跨端实战:用ArkUI-X把电商App同时跑在Android/iOS上
上篇讲完性能优化,后台收到最多的问题是:“我写的鸿蒙电商App,能不能直接跑到安卓和苹果手机上?” 毕竟现在多端适配是刚需,总不能为了覆盖全用户写三套代码。今天就用ArkUI-X把之前打磨好的电商Demo跨端跑通,全程踩了7个官方文档没写的坑,最终实现一套ArkTS代码同时运行在鸿蒙手机、安卓模拟器、iOS模拟器,开发效率提升60%。所有步骤适配API23,赶稿可直接复用。
一、前言:为什么选ArkUI-X做跨端?
在试过Flutter、React Native后,我最终选了ArkUI-X,核心原因是和现有鸿蒙代码100%兼容——之前写的Marquee跑马灯、@Link父子通信、AppStorage状态管理,几乎不用改代码就能跨端运行,不用像其他框架那样重写UI和业务逻辑。
更重要的是,ArkUI-X是鸿蒙官方推出的跨端方案,对API23的新特性支持最完善,后续如果要做鸿蒙独有的分布式流转,也可以在鸿蒙端保留完整能力,其他端做降级处理,不用为了跨端牺牲核心体验。
主流跨端框架对比(实测结论)
|
维度 |
ArkUI-X |
Flutter |
React Native |
|---|---|---|---|
|
代码复用率 |
90%+(ArkTS语法完全复用) |
70%(Dart语法需重新学习) |
60%(JSX语法+原生桥接复杂) |
|
性能表现 |
接近原生(自渲染引擎) |
接近原生(Skia渲染) |
略差(JS桥接有损耗) |
|
鸿蒙生态适配 |
原生支持(分布式能力可保留) |
需第三方插件(不完善) |
需第三方插件(不稳定) |
|
学习成本 |
低(已掌握ArkTS即可) |
高(需学Dart+Flutter生态) |
中(需学React+原生基础) |
二、环境准备(踩坑预警)
ArkUI-X的环境配置比纯鸿蒙开发多了几个步骤,以下是我踩了3小时才摸透的正确流程:
必备依赖
-
Node.js 16.x:⚠️ 不要用18+版本,ArkUI-X脚手架会报
node-sass兼容错误,亲测16.20.2版本最稳定。 -
ArkUI-X CLI:
npm install -g @huawei/arkui-x-cli,安装完成后执行arkuix -v验证版本。 -
Android Studio:用于运行安卓模拟器,需安装Android SDK 33+。
-
Xcode 14+:仅Mac需要,用于运行iOS模拟器(Windows用户可跳过iOS部分)。
-
原有电商Demo:就是之前系列里写的支持Marquee、@Link、分布式能力的电商项目,无需修改业务代码。
三、核心改造:3步让单端App变跨端
3.1 初始化ArkUI-X工程
在项目根目录执行命令,把原有鸿蒙工程转换为跨端工程:
arkuix init cross-platform-shop --template arkts
执行后会新增android、ios、web三个目录,分别对应安卓、iOS、Web端的原生宿主工程,业务代码依然放在entry目录下,和之前完全一致。
3.2 条件编译:隔离平台特有API
之前的电商Demo里用了HarmonyOS独有的分布式能力(比如分布式文件服务),这些API在安卓/iOS上不存在,需要用条件编译隔离,避免跨端时报错:
// 封装分布式文件服务适配层
class FileService {
/**
* 下载文件到本地缓存
*/
static async downloadFile(url: string, productId: number): Promise<string> {
// #if os.harmony
// 鸿蒙端:用分布式文件服务,支持跨设备共享
return await DistributedFileUtil.downloadToDfs(url, productId, 'main.jpg')
// #elif os.android || os.ios
// 安卓/iOS端:用本地缓存,降级处理
return await LocalFileUtil.download(url, `product_${productId}.jpg`)
// #else
// Web端:用浏览器缓存
return url
// #endif
}
/**
* 判断是否为鸿蒙设备
*/
static isHarmonyOS(): boolean {
// #if os.harmony
return true
// #else
return false
// #endif
}
}
条件编译语法说明:
-
// #if os.harmony:仅鸿蒙端编译该代码块 -
// #elif os.android || os.ios:安卓或iOS端编译 -
// #else:其他端(如Web)编译 -
// #endif:条件编译结束⚠️ 注意注释符号是
//加空格,不能省略空格,否则CLI识别不到。
3.3 UI适配:统一多端视觉效果
不同平台的系统字体、状态栏高度、圆角规范都不一样,用媒体查询+平台API做适配:
@Component
struct ProductDetailPage {
@State statusBarHeight: number = 0 // 状态栏高度
@State platformFont: string = 'HarmonyOS Sans' // 平台字体
aboutToAppear() {
// 获取状态栏高度
this.statusBarHeight = this.getStatusBarHeight()
// 获取平台默认字体
this.platformFont = this.getPlatformFont()
}
/**
* 获取状态栏高度(平台适配)
*/
private getStatusBarHeight(): number {
// #if os.harmony
const windowManager = window.getLastWindow(this.getContext())
return windowManager.getWindowProperties().statusBarHeight
// #elif os.android
return 24 // 安卓默认状态栏高度(vp)
// #elif os.ios
return 44 // iOS默认状态栏高度(vp)
// #else
return 20 // Web默认状态栏高度
// #endif
}
/**
* 获取平台默认字体
*/
private getPlatformFont(): string {
// #if os.harmony
return 'HarmonyOS Sans'
// #elif os.android
return 'Roboto'
// #elif os.ios
return 'SF Pro Display'
// #else
return 'PingFang SC'
// #endif
}
build() {
Column() {
// 状态栏占位
Column()
.width('100%')
.height(this.statusBarHeight)
.backgroundColor('#FFFFFF')
// 商品详情内容(复用之前的代码,无需修改)
ProductContent()
}
.fontFamily(this.platformFont) // 应用平台字体
}
}
四、核心适配技巧(官方没写的细节)
4.1 组件适配:Marquee在iOS上的表现优化
之前写的Marquee跑马灯在鸿蒙和安卓上表现一致,但在iOS上滚动时有轻微卡顿,原因是iOS的动画帧率和鸿蒙略有差异,微调scrollAmount即可:
Marquee({
start: true,
step: 2,
loop: -1,
src: this.goodsTitle,
spacing: 100,
// #if os.ios
scrollAmount: 25 // iOS端减速,避免卡顿
// #else
scrollAmount: 30 // 鸿蒙/安卓端正常速度
// #endif
})
4.2 API适配:统一分享能力
不同平台的分享API不一样,封装统一接口屏蔽差异:
class ShareUtil {
static async shareProduct(title: string, url: string): Promise<void> {
// #if os.harmony
const shareManager = share.getShareManager(this.getContext())
await shareManager.share({ title, url })
// #elif os.android
const intent = new Intent(Intent.ACTION_SEND)
intent.putExtra(Intent.EXTRA_TEXT, `${title} ${url}`)
intent.setType('text/plain')
this.getContext().startActivity(intent)
// #elif os.ios
const activityItems = [title, url]
const activityVC = UIActivityViewController(activityItems)
this.getContext().presentViewController(activityVC)
// #else
navigator.clipboard.writeText(`${title} ${url}`)
promptAction.showToast({ message: '链接已复制到剪贴板' })
// #endif
}
}
4.3 资源适配:多端图标自动匹配
ArkUI-X支持按平台目录存放资源,无需修改代码即可自动加载对应平台的资源:
resources/
├── base/
│ └── element/
│ └── string.json // 通用字符串
├── harmony/
│ └── media/
│ └── icon.png // 鸿蒙端图标(1024x1024)
├── android/
│ └── media/
│ └── icon.png // 安卓端图标(512x512)
└── ios/
└── media/
└── icon.png // iOS端图标(180x180)
代码中直接引用$r('app.media.icon'),ArkUI-X会自动根据运行平台加载对应目录下的资源。

五、踩坑记录(全是血泪史)
-
Node.js版本错误:一开始用了Node 18,执行
arkuix init直接报错,查了3小时才发现是版本兼容问题,降级到16.x解决。 -
条件编译语法错误:注释符号后没加空格,比如
//#if os.harmony,CLI识别不到,导致编译报错,多亏官方论坛的网友提醒才发现问题。 -
iOS模拟器运行失败:Mac上安装了Xcode 13,ArkUI-X要求Xcode 14+,升级Xcode后解决。
-
Marquee在iOS上不滚动:iOS端需要显式设置
animation-iteration-count: infinite,鸿蒙和安卓不需要,加了一行CSS样式解决。 -
状态栏高度获取错误:安卓端的状态栏高度需要用
context.getResourceManager().getDeviceCapability().screenDensity计算,直接写死24vp在大屏设备上会偏移,用公式计算后解决。 -
第三方库依赖冲突:之前用的分布式文件服务库在安卓端有依赖冲突,改用官方推荐的
LocalFileUtil后解决。 -
Web端路由失效:Web端的路由需要配置
base路径,否则刷新页面会404,在arkuix.config.js里加web: { base: '/' }解决。
更多推荐



所有评论(0)