文章目录前言一、ArkUI-X 与 ArkUI 原生同根同源各有侧重1.1 技术定位对比1.2 为什么不能「原样拷贝」二、分层架构复用的真正边界2.1 业务逻辑层55%—— 真正该复用的2.2 平台适配层25%—— 迁移成本集中区2.3 UI 呈现层20%—— 语法共享细节适配三、适配器模式实战Bridge 注入3.1 依赖注入而非条件编译3.2 在 Demo 中验证复用性3.3 Bridge 该抽象到什么粒度四、五大 API 差异与适配策略4.1 页面路由4.2 本地存储4.3 网络请求4.4 生命周期4.5 系统能力五、渐进式迁移路径六步 ChecklistPhase 1打基础不改 UI 也能做Phase 2替换与适配Phase 3原生化和收敛六、UI 代码到底能复用多少七、常见误区与反模式7.1 误区「ArkUI 语法一样 代码能直接跑」7.2 误区「用 #ifdef 最快」7.3 误区「双端同步维护 forever」7.4 误区「ViewModel 里偷偷调平台 API」7.5 反模式God Bridge八、面向未来的架构建议8.1 模块化拆分8.2 设计令牌Design Token共享8.3 测试策略九、决策树我该怎么选十、总结前言「一套代码多端运行」是移动端开发者长期追逐的目标。Flutter 用 Widget 树统一渲染React Native 用 JS 桥接原生组件HarmonyOS 生态则走出了另一条路——ArkUI 声明式 UI。ArkUI-X将 ArkUI 扩展到 Android、iOS 等平台让开发者用熟悉的 ArkTS 语法编写跨端应用ArkUI 原生则深度绑定 HarmonyOS享有完整 Kit 能力分布式、卡片、实况窗等。随着 HarmonyOS 原生生态成熟许多团队面临一个现实问题当初为跨端写的 ArkUI-X 代码如何平滑迁移到 ArkUI 原生哪些能复用哪些必须重写本文不承诺「100% 代码零修改迁移」——那是不切实际的。我们从分层架构、适配器模式、API 差异对照、渐进式迁移路径四个维度结合项目 Demo做一次概念性但可落地的思考。读完后你应该能回答跨平台复用的真正边界在哪里ViewModel Bridge 如何做到「逻辑不变、平台可换」路由、存储、网络等 API 差异如何屏蔽从 ArkUI-X 到原生推荐的六步迁移顺序是什么一、ArkUI-X 与 ArkUI 原生同根同源各有侧重1.1 技术定位对比维度ArkUI-XArkUI 原生目标平台HarmonyOS Android iOSHarmonyOS手机/平板/穿戴等UI 语法ArkUI 声明式Component、State同左API 更完整运行时跨端渲染引擎 平台桥接系统内置 ArkUI 引擎系统能力受限需 polyfill 或降级完整 KitNetwork、Distributed、Form 等生命周期跨端 Ability 抽象UIAbility Stage 模型典型场景多端统一、快速验证深度利用 HarmonyOS 特性两者共享声明式 UI 范式——Column、Row、Button、Text的写法高度相似。差异集中在平台 API 层和系统独占能力。1.2 为什么不能「原样拷贝」不少开发者初次迁移时的预期是把 ArkUI-X 工程复制一份改个编译目标就能跑。实际会遇到Kit 引用不通—kit.NetworkKit在跨端环境可能不可用路由栈差异— 原生Navigation组件与跨端router封装行为不同生命周期映射— Stage 模型的onWindowStageCreate在 ArkUI-X 中无直接对应独占能力缺失— 分布式流转、服务卡片、实况窗等原生 API 在跨端无等价物性能优化路径不同— 原生可直接用LazyForEach、Reusable等深度优化。因此迁移的核心不是「改编译配置」而是重新划定复用边界用架构手段隔离差异。二、分层架构复用的真正边界Demo 中提出的三层模型是本文一切讨论的基础┌─────────────────────────────────────────┐ │ UI 呈现层~20% │ │ Component · 布局 · 样式 · 动画 │ ← 语法可共享API 需适配 ├─────────────────────────────────────────┤ │ 平台适配层~25% │ │ IPlatformBridge · 路由/存储/Toast │ ← 各端独立实现 ├─────────────────────────────────────────┤ │ 业务逻辑层~55% │ │ ViewModel · 数据模型 · 校验 · 状态机 │ ← 平台无关核心复用区 └─────────────────────────────────────────┘2.1 业务逻辑层55%—— 真正该复用的这一层不 import 任何平台 Kit不引用router、Preferences、promptAction。只包含数据模型interface、class业务规则校验、计算、状态转换ViewModel驱动 UI 的状态与命令Demo 中的SharedCartViewModel就是标准范例classSharedCartViewModel{privatebridge:IPlatformBridge items:string[][]totalCount:number0constructor(bridge:IPlatformBridge){this.bridgebridge}addItem(name:string):string{if(name.trim().length0){return商品名不能为空}this.items[...this.items,name.trim()]this.totalCountthis.items.lengththis.bridge.savePreference(cart_count,${this.totalCount})this.bridge.showToast(已添加 ·${this.bridge.platformName})return1「${name.trim()}」→ 共${this.totalCount}件}checkout():string{if(this.totalCount0){return购物车为空无法结算}return结算${this.totalCount}件 ·${this.bridge.navigateTo(Checkout)}}}注意addItem里的校验逻辑空名拒绝、数组不可变更新[...this.items, name]、计数维护——全部是纯业务与平台无关。需要平台帮忙的地方存偏好、弹 Toast、跳转全部委托给bridge。2.2 平台适配层25%—— 迁移成本集中区适配层是 ArkUI-X 与原生之间的「翻译官」。Demo 定义了IPlatformBridge接口interfaceIPlatformBridge{readonlyplatformName:stringshowToast(message:string):voidsavePreference(key:string,value:string):stringreadPreference(key:string):stringnavigateTo(route:string):string}两端各自实现方法ArkUIXBridgeArkUINativeBridgesavePreferencepreferences.put(k, v)Preferences.put(k, v)navigateTorouter.pushUrl({ url })router.pushUrl({ url: pages/... })showToast跨端 Toast 封装promptAction.showToast切换平台 切换 Bridge 实现ViewModel 一行不改。Demo 顶部的「ArkUI-X / ArkUI 原生」切换器就是这个原理的 UI 化演示。2.3 UI 呈现层20%—— 语法共享细节适配ArkUI 声明式语法在两端高度相似// 两端几乎相同的写法Column({space:12}){Text(标题).fontSize(22).fontWeight(FontWeight.Bold)Button(提交).onClick((){this.viewModel.submit()})}但具体 API 可能有差异原生独有的bindSheet、Navigation嵌套路由、.id()测试属性等。UI 层可以共享设计规范和组件结构但不要强求「同一个.ets文件零修改编译通过」。三、适配器模式实战Bridge 注入3.1 依赖注入而非条件编译过渡期的常见写法// 不推荐散落各处的 #ifdefif(isHarmonyOS){Preferences.put(key,value)}else{crossPlatformStorage.set(key,value)}短期能用长期会变成「条件编译地狱」。推荐收敛到 Adapter// 推荐构造时注入constbridgeplatformnative?newArkUINativeBridge():newArkUIXBridge()constviewModelnewSharedCartViewModel(bridge)Demo 中syncBridge()方法privatesyncBridge():void{constbridge:IPlatformBridgethis.platformPlatformTarget.ARKUI_X?newArkUIXBridge():newArkUINativeBridge()this.viewModelnewSharedCartViewModel(bridge)}3.2 在 Demo 中验证复用性操作步骤进入「共享逻辑」场景输入商品名点击「添加商品」观察日志中的平台 API 调用[ArkUI-X] preferences.put或[Native] Preferences.put切换顶部平台切换器再次添加商品——业务结果一致底层 API 调用不同这就是「一套逻辑多端适配」的最小可验证单元。3.3 Bridge 该抽象到什么粒度原则抽象「业务需要的能力」而非「底层每一个 API」。该抽象不该抽象navigateTo(route)router.pushUrl的每一个参数showToast(msg)Toast 动画曲线savePreference(k, v)Preferences 实例创建细节requestPermission(name)权限弹窗 UI 样式粒度过细 → 适配层膨胀失去意义过粗 → 无法满足平台差异。以业务用例驱动接口设计。四、五大 API 差异与适配策略Demo「API 差异」场景列出了五类常见差异4.1 页面路由ArkUI-XArkUI 原生调用router.pushUrl跨端 SDKrouter.pushUrlNavigation栈差异路径约定、栈管理简化支持NavPathStack、嵌套导航策略IRouterBridge.push(route)统一入口4.2 本地存储ArkUI-XArkUI 原生调用ohos.data.storage兼容层Preferences/AppStorage差异异步 API 签名可能不同支持StorageLink状态同步策略IStorageBridge.get/set接口隔离4.3 网络请求ArkUI-XArkUI 原生调用axios/fetch通用方案kit.NetworkKit的http差异证书、代理配置方式不同系统级网络策略、VPN 感知策略HttpClient抽象类两端注入实现4.4 生命周期ArkUI-XArkUI 原生模型跨端 Ability 生命周期UIAbility Stage 模型关键回调简化版 onCreate/onDestroyonCreate→onWindowStageCreate→onForeground策略生命周期事件映射到 ViewModel 方法原生生命周期更丰富。建议 ViewModel 暴露语义化方法由 Ability 层桥接// EntryAbility.etsonForeground():void{this.viewModel.onAppForeground()}// ViewModel平台无关onAppForeground():void{this.refreshData()}4.5 系统能力ArkUI-XArkUI 原生能力范围受限需 polyfill完整 Kit独占示例—分布式流转、服务卡片、实况窗策略能力探测 优雅降级interfaceIPlatformBridge{// 可选能力原生有实现跨端返回 falsesupportsDistributed():booleanstartContinuation?(data:object):void}跨端调用时检查supportsDistributed()为false则隐藏相关 UI 入口而非崩溃。五、渐进式迁移路径六步 ChecklistDemo「迁移路径」场景提供了可交互的六步清单Phase 1打基础不改 UI 也能做Step 1剥离业务逻辑将State中的计算、校验、网络回调逻辑下沉到 ViewModel。UI 组件只负责「绑定状态」和「转发事件」// 迁移前逻辑散落在 Component 中Statecount:number0Button(1).onClick((){this.count;this.save();this.toast()})// 迁移后Component 变瘦Button(1).onClick((){this.logthis.viewModel.addItem(this.input)})Step 2定义 PlatformBridge梳理所有平台 API 调用点归纳为 Bridge 接口。先定义接口、再做实现可与 Step 1 并行。Phase 2替换与适配Step 3替换 ArkUI-X 特有 API全局搜索跨端 SDK 引用逐一映射到原生 Kit。建议按模块推进先网络再存储再路由。Step 4适配 Stage 模型EntryAbility继承UIAbilityonWindowStageCreate中loadContent(pages/Index)前后台切换通过onForeground/onBackground同步 ViewModelPhase 3原生化和收敛Step 5接入原生独占特性分布式数据同步、服务卡片、实况窗等——这些是迁移到原生的「收益」应在 Bridge 可选接口中实现。Step 6移除跨端兼容层删除ArkUIXBridge、polyfill、条件编译分支收敛为单端代码库。如果仍需保留 Android/iOS 端将 Bridge 实现拆到独立 module。六、UI 代码到底能复用多少这是开发者最关心的问题。诚实回答代码类型复用度说明数据模型 / interface90%几乎原样复用ViewModel / 业务逻辑70–80%剥离平台调用后复用布局结构Column/Row 嵌套50–60%语法同尺寸/断点可能不同样式与主题30–40%设计令牌可共享具体值需调平台 API 调用0%必须走 Bridge 各端实现原生独占特性 UI0%原生新增跨端不存在Demo 中的比例55% / 25% / 20%是经验估值具体项目需按模块盘点。可用简单公式估算复用率 ≈ (ViewModel 行数 数据模型行数) / 总业务代码行数不要追求 100% UI 复用——那会以牺牲原生体验为代价。合理目标是逻辑层最大化复用UI 层共享设计规范适配层隔离差异。七、常见误区与反模式7.1 误区「ArkUI 语法一样 代码能直接跑」语法相似不等于 API 兼容。ohos.*模块在跨端环境可能不存在或行为不同。必须逐模块验证。7.2 误区「用 #ifdef 最快」条件编译适合极少量平台分支如日志标签。如果#ifdef超过 20 处说明抽象不够应回流到 Bridge。7.3 误区「双端同步维护 forever」如果 HarmonyOS 原生已是主战场应明确「原生优先」策略新特性只在原生 Bridge 实现跨端端接受能力降级而非两端对等开发。7.4 误区「ViewModel 里偷偷调平台 API」ViewModel 中一旦出现import router from ohos.router复用性立刻归零。所有平台调用必须通过 Bridge。7.5 反模式God Bridge一个 Bridge 接口塞满 50 个方法变成新的「平台上帝对象」。按领域拆分IStorageBridge IRouterBridge INetworkBridge INotificationBridge各 ViewModel 只依赖需要的子接口。八、面向未来的架构建议8.1 模块化拆分project/ ├── common_logic/ ← HARViewModel 数据模型平台无关 ├── platform_bridge/ ← HARIPlatformBridge 接口定义 ├── bridge_native/ ← HARArkUINativeBridge 实现 ├── bridge_arkui_x/ ← HARArkUIXBridge 实现如需保留 └── entry/ ← HAPUI 页面 EntryAbilitycommon_logic不依赖任何 Bridge 实现只依赖接口。编译期通过 HAR 依赖注入具体实现。8.2 设计令牌Design Token共享颜色、字号、间距、圆角等视觉常量可放在common_logic或独立design_tokens模块exportconstDSTokens{primaryColor:#2563EB,titleSize:22,cardRadius:12}UI 层两端引用同一套 Token保证视觉一致同时允许各端覆盖特殊值。8.3 测试策略层测试方式ViewModel单元测试注入 MockBridgeBridge 实现仪器测试 / 集成测试UIHypium UI 测试原生端MockBridge 示例classMockBridgeimplementsIPlatformBridge{readonlyplatformNameMocklastToast:stringshowToast(msg:string):void{this.lastToastmsg}savePreference(key:string,value:string):string{returnmock_saved}readPreference(key:string):string{return0}navigateTo(route:string):string{returnmock_nav_${route}}}// 单元测试constvmnewSharedCartViewModel(newMockBridge())vm.addItem(测试商品)expect(vm.totalCount).assertEqual(1)ViewModel 的平台无关性让单元测试可以在 DevEco 本地直接跑无需设备。九、决策树我该怎么选开始 │ ┌───────────┴───────────┐ │ 是否需要 Android/iOS │ └───────────┬───────────┘ 是 ╱ ╲ 否 ╱ ╲ ArkUI-X ArkUI 原生 跨端开发 直接原生 │ │ │ 充分利用 Kit 能力 │ │ ┌─────┴─────┐ │ │ 原生是主战场│ │ └─────┬─────┘ │ 是 ╱ ╲ 否 │ ╱ ╲ │ 渐进迁移 继续跨端 │ (本文路径) 维护双端 │建议纯 HarmonyOS 应用 → 直接用 ArkUI 原生不必绕道 ArkUI-X已用 ArkUI-X 且需保留多端 → Bridge 架构 原生优先新特性已用 ArkUI-X 但只需 HarmonyOS → 按六步 Checklist 渐进迁移最终收敛单端十、总结从 ArkUI-X 到 ArkUI 原生不是简单的「改个编译目标」而是一次架构重新审视复用核心在逻辑层~55%不在逐行 UI 适配成本在 Bridge 层~25%用接口隔离 UI 层共享语法和设计规范~20%不强求文件级复用关键技术手段手段作用ViewModel业务逻辑平台无关IPlatformBridge平台 API 抽象依赖注入运行时切换平台实现渐进迁移六步 Checklist 降低风险能力探测原生独占特性优雅降级本文 Demo 以SharedCartViewModel为载体在「共享逻辑」场景中切换 ArkUI-X / 原生 Bridge直观展示「逻辑不变、平台可换」。建议你在真机上操作一遍添加商品 → 切换平台 → 再添加 → 对比日志中的 API 差异。跨平台不是目的用合理的架构降低多端成本才是。Whether you stay on ArkUI-X or go all-in on native, the layered thinking in this article will save you from rewriting everything from scratch.相关文件entry/src/main/ets/pages/Index.ets编译命令node/Applications/DevEco-Studio.app/Contents/tools/hvigor/bin/hvigorw.js assembleHap-pproductdefault-pbuildModedebug --no-daemon
从 ArkUI-X 到 ArkUI 原生 —— 跨平台代码复用的思考
文章目录前言一、ArkUI-X 与 ArkUI 原生同根同源各有侧重1.1 技术定位对比1.2 为什么不能「原样拷贝」二、分层架构复用的真正边界2.1 业务逻辑层55%—— 真正该复用的2.2 平台适配层25%—— 迁移成本集中区2.3 UI 呈现层20%—— 语法共享细节适配三、适配器模式实战Bridge 注入3.1 依赖注入而非条件编译3.2 在 Demo 中验证复用性3.3 Bridge 该抽象到什么粒度四、五大 API 差异与适配策略4.1 页面路由4.2 本地存储4.3 网络请求4.4 生命周期4.5 系统能力五、渐进式迁移路径六步 ChecklistPhase 1打基础不改 UI 也能做Phase 2替换与适配Phase 3原生化和收敛六、UI 代码到底能复用多少七、常见误区与反模式7.1 误区「ArkUI 语法一样 代码能直接跑」7.2 误区「用 #ifdef 最快」7.3 误区「双端同步维护 forever」7.4 误区「ViewModel 里偷偷调平台 API」7.5 反模式God Bridge八、面向未来的架构建议8.1 模块化拆分8.2 设计令牌Design Token共享8.3 测试策略九、决策树我该怎么选十、总结前言「一套代码多端运行」是移动端开发者长期追逐的目标。Flutter 用 Widget 树统一渲染React Native 用 JS 桥接原生组件HarmonyOS 生态则走出了另一条路——ArkUI 声明式 UI。ArkUI-X将 ArkUI 扩展到 Android、iOS 等平台让开发者用熟悉的 ArkTS 语法编写跨端应用ArkUI 原生则深度绑定 HarmonyOS享有完整 Kit 能力分布式、卡片、实况窗等。随着 HarmonyOS 原生生态成熟许多团队面临一个现实问题当初为跨端写的 ArkUI-X 代码如何平滑迁移到 ArkUI 原生哪些能复用哪些必须重写本文不承诺「100% 代码零修改迁移」——那是不切实际的。我们从分层架构、适配器模式、API 差异对照、渐进式迁移路径四个维度结合项目 Demo做一次概念性但可落地的思考。读完后你应该能回答跨平台复用的真正边界在哪里ViewModel Bridge 如何做到「逻辑不变、平台可换」路由、存储、网络等 API 差异如何屏蔽从 ArkUI-X 到原生推荐的六步迁移顺序是什么一、ArkUI-X 与 ArkUI 原生同根同源各有侧重1.1 技术定位对比维度ArkUI-XArkUI 原生目标平台HarmonyOS Android iOSHarmonyOS手机/平板/穿戴等UI 语法ArkUI 声明式Component、State同左API 更完整运行时跨端渲染引擎 平台桥接系统内置 ArkUI 引擎系统能力受限需 polyfill 或降级完整 KitNetwork、Distributed、Form 等生命周期跨端 Ability 抽象UIAbility Stage 模型典型场景多端统一、快速验证深度利用 HarmonyOS 特性两者共享声明式 UI 范式——Column、Row、Button、Text的写法高度相似。差异集中在平台 API 层和系统独占能力。1.2 为什么不能「原样拷贝」不少开发者初次迁移时的预期是把 ArkUI-X 工程复制一份改个编译目标就能跑。实际会遇到Kit 引用不通—kit.NetworkKit在跨端环境可能不可用路由栈差异— 原生Navigation组件与跨端router封装行为不同生命周期映射— Stage 模型的onWindowStageCreate在 ArkUI-X 中无直接对应独占能力缺失— 分布式流转、服务卡片、实况窗等原生 API 在跨端无等价物性能优化路径不同— 原生可直接用LazyForEach、Reusable等深度优化。因此迁移的核心不是「改编译配置」而是重新划定复用边界用架构手段隔离差异。二、分层架构复用的真正边界Demo 中提出的三层模型是本文一切讨论的基础┌─────────────────────────────────────────┐ │ UI 呈现层~20% │ │ Component · 布局 · 样式 · 动画 │ ← 语法可共享API 需适配 ├─────────────────────────────────────────┤ │ 平台适配层~25% │ │ IPlatformBridge · 路由/存储/Toast │ ← 各端独立实现 ├─────────────────────────────────────────┤ │ 业务逻辑层~55% │ │ ViewModel · 数据模型 · 校验 · 状态机 │ ← 平台无关核心复用区 └─────────────────────────────────────────┘2.1 业务逻辑层55%—— 真正该复用的这一层不 import 任何平台 Kit不引用router、Preferences、promptAction。只包含数据模型interface、class业务规则校验、计算、状态转换ViewModel驱动 UI 的状态与命令Demo 中的SharedCartViewModel就是标准范例classSharedCartViewModel{privatebridge:IPlatformBridge items:string[][]totalCount:number0constructor(bridge:IPlatformBridge){this.bridgebridge}addItem(name:string):string{if(name.trim().length0){return商品名不能为空}this.items[...this.items,name.trim()]this.totalCountthis.items.lengththis.bridge.savePreference(cart_count,${this.totalCount})this.bridge.showToast(已添加 ·${this.bridge.platformName})return1「${name.trim()}」→ 共${this.totalCount}件}checkout():string{if(this.totalCount0){return购物车为空无法结算}return结算${this.totalCount}件 ·${this.bridge.navigateTo(Checkout)}}}注意addItem里的校验逻辑空名拒绝、数组不可变更新[...this.items, name]、计数维护——全部是纯业务与平台无关。需要平台帮忙的地方存偏好、弹 Toast、跳转全部委托给bridge。2.2 平台适配层25%—— 迁移成本集中区适配层是 ArkUI-X 与原生之间的「翻译官」。Demo 定义了IPlatformBridge接口interfaceIPlatformBridge{readonlyplatformName:stringshowToast(message:string):voidsavePreference(key:string,value:string):stringreadPreference(key:string):stringnavigateTo(route:string):string}两端各自实现方法ArkUIXBridgeArkUINativeBridgesavePreferencepreferences.put(k, v)Preferences.put(k, v)navigateTorouter.pushUrl({ url })router.pushUrl({ url: pages/... })showToast跨端 Toast 封装promptAction.showToast切换平台 切换 Bridge 实现ViewModel 一行不改。Demo 顶部的「ArkUI-X / ArkUI 原生」切换器就是这个原理的 UI 化演示。2.3 UI 呈现层20%—— 语法共享细节适配ArkUI 声明式语法在两端高度相似// 两端几乎相同的写法Column({space:12}){Text(标题).fontSize(22).fontWeight(FontWeight.Bold)Button(提交).onClick((){this.viewModel.submit()})}但具体 API 可能有差异原生独有的bindSheet、Navigation嵌套路由、.id()测试属性等。UI 层可以共享设计规范和组件结构但不要强求「同一个.ets文件零修改编译通过」。三、适配器模式实战Bridge 注入3.1 依赖注入而非条件编译过渡期的常见写法// 不推荐散落各处的 #ifdefif(isHarmonyOS){Preferences.put(key,value)}else{crossPlatformStorage.set(key,value)}短期能用长期会变成「条件编译地狱」。推荐收敛到 Adapter// 推荐构造时注入constbridgeplatformnative?newArkUINativeBridge():newArkUIXBridge()constviewModelnewSharedCartViewModel(bridge)Demo 中syncBridge()方法privatesyncBridge():void{constbridge:IPlatformBridgethis.platformPlatformTarget.ARKUI_X?newArkUIXBridge():newArkUINativeBridge()this.viewModelnewSharedCartViewModel(bridge)}3.2 在 Demo 中验证复用性操作步骤进入「共享逻辑」场景输入商品名点击「添加商品」观察日志中的平台 API 调用[ArkUI-X] preferences.put或[Native] Preferences.put切换顶部平台切换器再次添加商品——业务结果一致底层 API 调用不同这就是「一套逻辑多端适配」的最小可验证单元。3.3 Bridge 该抽象到什么粒度原则抽象「业务需要的能力」而非「底层每一个 API」。该抽象不该抽象navigateTo(route)router.pushUrl的每一个参数showToast(msg)Toast 动画曲线savePreference(k, v)Preferences 实例创建细节requestPermission(name)权限弹窗 UI 样式粒度过细 → 适配层膨胀失去意义过粗 → 无法满足平台差异。以业务用例驱动接口设计。四、五大 API 差异与适配策略Demo「API 差异」场景列出了五类常见差异4.1 页面路由ArkUI-XArkUI 原生调用router.pushUrl跨端 SDKrouter.pushUrlNavigation栈差异路径约定、栈管理简化支持NavPathStack、嵌套导航策略IRouterBridge.push(route)统一入口4.2 本地存储ArkUI-XArkUI 原生调用ohos.data.storage兼容层Preferences/AppStorage差异异步 API 签名可能不同支持StorageLink状态同步策略IStorageBridge.get/set接口隔离4.3 网络请求ArkUI-XArkUI 原生调用axios/fetch通用方案kit.NetworkKit的http差异证书、代理配置方式不同系统级网络策略、VPN 感知策略HttpClient抽象类两端注入实现4.4 生命周期ArkUI-XArkUI 原生模型跨端 Ability 生命周期UIAbility Stage 模型关键回调简化版 onCreate/onDestroyonCreate→onWindowStageCreate→onForeground策略生命周期事件映射到 ViewModel 方法原生生命周期更丰富。建议 ViewModel 暴露语义化方法由 Ability 层桥接// EntryAbility.etsonForeground():void{this.viewModel.onAppForeground()}// ViewModel平台无关onAppForeground():void{this.refreshData()}4.5 系统能力ArkUI-XArkUI 原生能力范围受限需 polyfill完整 Kit独占示例—分布式流转、服务卡片、实况窗策略能力探测 优雅降级interfaceIPlatformBridge{// 可选能力原生有实现跨端返回 falsesupportsDistributed():booleanstartContinuation?(data:object):void}跨端调用时检查supportsDistributed()为false则隐藏相关 UI 入口而非崩溃。五、渐进式迁移路径六步 ChecklistDemo「迁移路径」场景提供了可交互的六步清单Phase 1打基础不改 UI 也能做Step 1剥离业务逻辑将State中的计算、校验、网络回调逻辑下沉到 ViewModel。UI 组件只负责「绑定状态」和「转发事件」// 迁移前逻辑散落在 Component 中Statecount:number0Button(1).onClick((){this.count;this.save();this.toast()})// 迁移后Component 变瘦Button(1).onClick((){this.logthis.viewModel.addItem(this.input)})Step 2定义 PlatformBridge梳理所有平台 API 调用点归纳为 Bridge 接口。先定义接口、再做实现可与 Step 1 并行。Phase 2替换与适配Step 3替换 ArkUI-X 特有 API全局搜索跨端 SDK 引用逐一映射到原生 Kit。建议按模块推进先网络再存储再路由。Step 4适配 Stage 模型EntryAbility继承UIAbilityonWindowStageCreate中loadContent(pages/Index)前后台切换通过onForeground/onBackground同步 ViewModelPhase 3原生化和收敛Step 5接入原生独占特性分布式数据同步、服务卡片、实况窗等——这些是迁移到原生的「收益」应在 Bridge 可选接口中实现。Step 6移除跨端兼容层删除ArkUIXBridge、polyfill、条件编译分支收敛为单端代码库。如果仍需保留 Android/iOS 端将 Bridge 实现拆到独立 module。六、UI 代码到底能复用多少这是开发者最关心的问题。诚实回答代码类型复用度说明数据模型 / interface90%几乎原样复用ViewModel / 业务逻辑70–80%剥离平台调用后复用布局结构Column/Row 嵌套50–60%语法同尺寸/断点可能不同样式与主题30–40%设计令牌可共享具体值需调平台 API 调用0%必须走 Bridge 各端实现原生独占特性 UI0%原生新增跨端不存在Demo 中的比例55% / 25% / 20%是经验估值具体项目需按模块盘点。可用简单公式估算复用率 ≈ (ViewModel 行数 数据模型行数) / 总业务代码行数不要追求 100% UI 复用——那会以牺牲原生体验为代价。合理目标是逻辑层最大化复用UI 层共享设计规范适配层隔离差异。七、常见误区与反模式7.1 误区「ArkUI 语法一样 代码能直接跑」语法相似不等于 API 兼容。ohos.*模块在跨端环境可能不存在或行为不同。必须逐模块验证。7.2 误区「用 #ifdef 最快」条件编译适合极少量平台分支如日志标签。如果#ifdef超过 20 处说明抽象不够应回流到 Bridge。7.3 误区「双端同步维护 forever」如果 HarmonyOS 原生已是主战场应明确「原生优先」策略新特性只在原生 Bridge 实现跨端端接受能力降级而非两端对等开发。7.4 误区「ViewModel 里偷偷调平台 API」ViewModel 中一旦出现import router from ohos.router复用性立刻归零。所有平台调用必须通过 Bridge。7.5 反模式God Bridge一个 Bridge 接口塞满 50 个方法变成新的「平台上帝对象」。按领域拆分IStorageBridge IRouterBridge INetworkBridge INotificationBridge各 ViewModel 只依赖需要的子接口。八、面向未来的架构建议8.1 模块化拆分project/ ├── common_logic/ ← HARViewModel 数据模型平台无关 ├── platform_bridge/ ← HARIPlatformBridge 接口定义 ├── bridge_native/ ← HARArkUINativeBridge 实现 ├── bridge_arkui_x/ ← HARArkUIXBridge 实现如需保留 └── entry/ ← HAPUI 页面 EntryAbilitycommon_logic不依赖任何 Bridge 实现只依赖接口。编译期通过 HAR 依赖注入具体实现。8.2 设计令牌Design Token共享颜色、字号、间距、圆角等视觉常量可放在common_logic或独立design_tokens模块exportconstDSTokens{primaryColor:#2563EB,titleSize:22,cardRadius:12}UI 层两端引用同一套 Token保证视觉一致同时允许各端覆盖特殊值。8.3 测试策略层测试方式ViewModel单元测试注入 MockBridgeBridge 实现仪器测试 / 集成测试UIHypium UI 测试原生端MockBridge 示例classMockBridgeimplementsIPlatformBridge{readonlyplatformNameMocklastToast:stringshowToast(msg:string):void{this.lastToastmsg}savePreference(key:string,value:string):string{returnmock_saved}readPreference(key:string):string{return0}navigateTo(route:string):string{returnmock_nav_${route}}}// 单元测试constvmnewSharedCartViewModel(newMockBridge())vm.addItem(测试商品)expect(vm.totalCount).assertEqual(1)ViewModel 的平台无关性让单元测试可以在 DevEco 本地直接跑无需设备。九、决策树我该怎么选开始 │ ┌───────────┴───────────┐ │ 是否需要 Android/iOS │ └───────────┬───────────┘ 是 ╱ ╲ 否 ╱ ╲ ArkUI-X ArkUI 原生 跨端开发 直接原生 │ │ │ 充分利用 Kit 能力 │ │ ┌─────┴─────┐ │ │ 原生是主战场│ │ └─────┬─────┘ │ 是 ╱ ╲ 否 │ ╱ ╲ │ 渐进迁移 继续跨端 │ (本文路径) 维护双端 │建议纯 HarmonyOS 应用 → 直接用 ArkUI 原生不必绕道 ArkUI-X已用 ArkUI-X 且需保留多端 → Bridge 架构 原生优先新特性已用 ArkUI-X 但只需 HarmonyOS → 按六步 Checklist 渐进迁移最终收敛单端十、总结从 ArkUI-X 到 ArkUI 原生不是简单的「改个编译目标」而是一次架构重新审视复用核心在逻辑层~55%不在逐行 UI 适配成本在 Bridge 层~25%用接口隔离 UI 层共享语法和设计规范~20%不强求文件级复用关键技术手段手段作用ViewModel业务逻辑平台无关IPlatformBridge平台 API 抽象依赖注入运行时切换平台实现渐进迁移六步 Checklist 降低风险能力探测原生独占特性优雅降级本文 Demo 以SharedCartViewModel为载体在「共享逻辑」场景中切换 ArkUI-X / 原生 Bridge直观展示「逻辑不变、平台可换」。建议你在真机上操作一遍添加商品 → 切换平台 → 再添加 → 对比日志中的 API 差异。跨平台不是目的用合理的架构降低多端成本才是。Whether you stay on ArkUI-X or go all-in on native, the layered thinking in this article will save you from rewriting everything from scratch.相关文件entry/src/main/ets/pages/Index.ets编译命令node/Applications/DevEco-Studio.app/Contents/tools/hvigor/bin/hvigorw.js assembleHap-pproductdefault-pbuildModedebug --no-daemon