HotGameRecommendPage 组件采用了现代 React 函数组件架构,结合 useState Hook 实现了精细化的状态管理。应用通过两个状态变量控制不同的 UI 状态:games 存储热门游戏列表,activeTab 控制当前激活的标签页。

GameCard 组件作为独立的子组件,负责渲染单个游戏的详细信息,通过 props 接收游戏数据和回调函数,实现了组件的复用和逻辑分离。这种组件化设计使得代码结构清晰,易于维护和扩展。

在数据结构上,使用了结构化的游戏数据格式,包含游戏的各项属性如标题、分类、开发商、评分、下载量等。这种数据结构设计合理,能够满足游戏推荐页面的各种功能需求。

布局

应用采用了现代化的移动应用布局设计,主要包含头部、搜索栏、标签页、游戏列表和底部导航栏五个部分。布局设计上,使用了 SafeAreaView 确保在不同设备上的显示兼容性,使用 ScrollView 确保在内容较长时可以滚动查看。

视觉设计上,使用了简洁明了的风格,通过不同的样式区分不同的功能区域和状态。游戏卡片的设计美观大方,包含游戏图片、分类、评分、标题、开发商、描述、统计信息、标签和操作按钮,为用户提供了丰富的视觉信息。标签页的水平滚动设计,为用户提供了便捷的分类浏览方式。

交互

应用实现了丰富的交互功能,包括:

  1. 标签页切换:通过标签按钮切换不同类型的游戏,为用户提供了便捷的游戏分类查看方式。
  2. 游戏下载:点击下载按钮,通过 Alert.alert 提供下载反馈。
  3. 游戏分享:点击分享按钮,通过 Alert.alert 提供分享反馈。
  4. 搜索功能:点击搜索栏,通过 Alert.alert 提供搜索反馈。
  5. 用户按钮:点击头部的用户图标,为用户提供了个人中心入口。

这些交互功能的实现遵循了 React 的最佳实践,通过状态更新驱动 UI 变化,确保了交互的一致性和可靠性。特别是游戏卡片的下载和分享功能,通过 Alert.alert 提供了明确的操作反馈,提升了用户体验。


在 React Native 与鸿蒙系统跨端开发中,该应用展现了多项兼容性设计:

  1. 基础组件选择:使用了 SafeAreaViewScrollViewTouchableOpacityImage 等基础组件,这些组件在 React Native 和鸿蒙系统中都有对应的实现。

  2. 样式管理:通过 StyleSheet.create 管理样式,确保了在不同平台上的一致表现。

  3. 资源管理:使用网络图片作为游戏封面,避免了平台差异带来的资源管理问题。使用 emoji 作为图标,确保了在不同平台上的一致显示。

  4. 状态管理:使用 useState Hook 进行状态管理,在鸿蒙系统中可以通过相应的状态管理机制(如 @State 装饰器)实现类似功能。

  5. 布局系统:使用了 Flexbox 布局系统,这是 React Native 和鸿蒙系统都支持的布局方式,确保了在不同平台上的一致布局效果。

  6. API 兼容性:使用了 Alert.alert 等跨平台 API,确保了在不同平台上的一致表现。


应用实现了多项性能优化策略,包括:

  1. 组件拆分:将游戏卡片拆分为独立的 GameCard 组件,提高了代码的可维护性和可测试性。

  2. 状态管理优化:使用 useState Hook 进行状态管理,对于这种中等复杂度的应用,避免了引入重型状态管理库的必要性。

  3. 渲染优化:通过 map 方法渲染游戏列表,代码简洁明了,适合中小规模的列表数据。

  4. 样式复用:通过 StyleSheet.create 管理样式,避免了在每次渲染时重新创建样式对象,提高了渲染性能。

  5. 条件渲染:通过条件样式(如 activeTab === tab && styles.activeTab)实现了标签页的选中效果,避免了使用条件渲染可能带来的额外渲染开销。


在将该应用适配到鸿蒙系统时,需要注意以下几点:

  1. 组件映射:将 React Native 的 SafeAreaViewScrollViewTouchableOpacityImage 等组件映射到鸿蒙系统的对应组件。例如,Image 可以映射到鸿蒙的 Image 组件,TouchableOpacity 可以映射到鸿蒙的 Button 组件。

  2. 样式转换:将 React Native 的 StyleSheet 样式转换为鸿蒙系统支持的样式格式。例如,React Native 的 flexDirection: 'row' 对应鸿蒙的 flexDirection: FlexDirection.Row

  3. 状态管理:鸿蒙系统的状态管理机制与 React Native 不同,需要进行适当的调整。例如,可以使用鸿蒙的 @State 装饰器替代 useState Hook。

  4. 事件处理:鸿蒙系统的事件处理机制与 React Native 不同,需要进行适当的调整。例如,鸿蒙系统的点击事件处理方式与 React Native 不同。

  5. 布局系统:虽然 Flexbox 布局在鸿蒙系统中也得到支持,但具体的实现细节可能有所不同,需要进行适当的调整。

  6. 性能优化:根据鸿蒙系统的特性,进行针对性的性能优化,确保应用在鸿蒙设备上运行流畅。例如,合理使用鸿蒙的缓存机制和渲染优化策略。

  7. API 适配:确保 Alert.alert 等 API 在鸿蒙系统中有对应的实现。例如,可以使用鸿蒙的 promptAction 或自定义弹窗组件。

总结

该热门游戏推荐应用展示了一个功能完整、设计优雅的 React Native 应用实现,涵盖了状态管理、组件架构、布局设计、交互处理等多个方面的技术点。通过合理的组件架构和状态管理,以及对跨端兼容性的考虑,该应用不仅在 React Native 环境下运行良好,也为后续的鸿蒙系统适配奠定了基础。


在React Native(RN)鸿蒙跨端开发中,页面级别的组件设计与适配是衔接基础API与业务落地的核心环节,尤其对于游戏推荐这类包含多元素渲染、复杂交互、自适应布局的场景,代码的合理性直接决定了跨端复用效率与鸿蒙设备上的用户体验。本文将以热门游戏推荐页面(HotGameRecommendPage)代码为载体,从跨端架构设计、组件化封装、鸿蒙适配细节、状态管理、交互逻辑五大维度,用技术博客的解读方式,深入剖析RN代码如何无缝适配鸿蒙系统,实现iOS、Android、鸿蒙三端一致的页面呈现与交互效果,为开发者提供可直接复用的页面级跨端开发参考。

本次解读的热门游戏推荐页面,是典型的内容展示类跨端页面,涵盖头部导航、搜索栏、标签页切换、游戏卡片列表、底部导航五大核心模块,集成了图片渲染、列表循环、触摸交互、弹窗提示、横向滚动等RN高频开发场景。整体代码基于RN官方核心API开发,未引入任何第三方依赖或平台特定原生代码,完全遵循“一次开发、多端复用”的鸿蒙跨端开发理念,既保证了代码的简洁性与可维护性,又最大化降低了鸿蒙适配的复杂度,尤其适合内容展示类APP的跨端页面开发参考。

不同于复杂的业务逻辑页面,游戏推荐页面的核心需求是“布局自适应、交互流畅化、视觉一致性”,这也正是RN鸿蒙跨端开发中内容类页面的核心痛点——鸿蒙系统涵盖手机、平板等多形态设备,屏幕宽高差异较大,若布局设计不合理,极易出现元素拉伸、错位、遮挡等问题;同时,鸿蒙系统对RN组件的渲染机制有细微差异,若未关注适配细节,可能导致交互异常、样式错乱等问题。而本次解读的代码,通过合理的组件封装、灵活的布局设计、细致的适配处理,完美规避了这些坑点,实现了鸿蒙多设备的无缝适配。

一、RN官方API:

RN鸿蒙跨端开发的核心优势,在于其官方核心API可直接映射为鸿蒙原生组件,开发者无需为鸿蒙设备单独编写适配代码,只需基于RN API开发页面逻辑,即可通过RN框架自动完成鸿蒙适配。本次热门游戏推荐页面,全程使用RN官方核心组件构建,包括布局组件(SafeAreaView、View)、文本组件(Text)、滚动组件(ScrollView)、触摸交互组件(TouchableOpacity)、图片组件(Image),以及样式管理(StyleSheet)、设备信息获取(Dimensions)、弹窗提示(Alert)等核心API,所有组件与API均能完美适配鸿蒙系统,实现多端布局与交互的一致性。

页面整体采用“模块化拆分、分层布局”的设计思路,将整个页面拆分为头部、搜索栏、标签页、内容区、底部导航五个独立模块,每个模块承担单一职责,互不干扰,这种设计不仅便于代码的维护与扩展,更利于鸿蒙跨端适配——当需要适配鸿蒙平板等不同形态设备时,可单独调整某个模块的布局逻辑,无需修改整个页面的核心代码。例如,若需优化平板设备上的标签页布局,只需调整标签页模块的样式与滚动逻辑,无需影响其他模块的正常运行。

其中,SafeAreaView作为页面的根容器,是鸿蒙跨端布局适配的基础。在鸿蒙全面屏手机、平板等设备上,状态栏、底部导航栏会占用一定的屏幕空间,若未使用SafeAreaView,极易出现页面内容被遮挡的问题。RN的SafeAreaView组件可自动识别鸿蒙设备的安全区域,将页面内容限制在安全区域内,无需额外编写适配代码,即可确保头部标题、底部导航等核心元素在鸿蒙多设备上均能正常显示,不出现遮挡、偏移等问题,为页面的跨端布局奠定了坚实基础。

此外,Dimensions组件的灵活运用,为鸿蒙多形态设备的自适应布局提供了保障。代码中通过const { width } = Dimensions.get(‘window’)动态获取当前设备的屏幕宽度,后续可基于该宽度实现组件的自适应尺寸计算(本次代码中预留了宽度计算的入口,可直接扩展用于网格布局、卡片尺寸适配等场景)。这种方式可确保页面组件在不同宽度的鸿蒙设备上,均能保持合理的布局比例,避免出现元素拉伸、挤压、换行等问题,尤其适合游戏卡片、标签页等需要自适应的组件。

二、组件化封装:

组件化封装是RN鸿蒙跨端开发的核心技巧之一,对于内容展示类页面而言,重复元素的封装的可大幅提升代码复用率,降低跨端适配成本。本次热门游戏推荐页面中,最核心的组件封装是GameCard游戏卡片组件,该组件封装了游戏图片、游戏信息、标签、下载/分享按钮等所有游戏卡片相关的UI与交互逻辑,通过props接收外部传递的游戏数据与回调函数,实现了组件的高复用性与低耦合性,同时确保了鸿蒙跨端适配的一致性。

GameCard组件采用函数式组件设计,符合RN当前的主流开发模式,同时适配鸿蒙系统对RN函数式组件的渲染机制——鸿蒙系统中,RN函数式组件的运行机制与iOS、Android完全一致,无需任何修改即可正常渲染。组件的props设计简洁清晰,包含game(游戏数据)、onDownload(下载回调)、onShare(分享回调)三个核心参数,其中game参数用于接收单个游戏的详细数据(包括标题、分类、开发商、评分等),onDownload与onShare用于接收外部传递的交互回调,实现组件与父组件的通信,这种设计既保证了组件的独立性,又便于父组件统一管理交互逻辑,提升代码的可维护性。

在组件内部,布局采用flex布局结合固定样式的方式,确保鸿蒙多设备上的视觉一致性。例如,游戏卡片的容器设置了固定的borderRadius、elevation、shadow等样式,实现卡片的阴影效果与圆角效果——这里需要重点说明的是,鸿蒙系统中,RN的shadow相关样式(shadowColor、shadowOffset、shadowOpacity、shadowRadius)可正常渲染,同时配合elevation属性(Android专属,鸿蒙系统可兼容),可确保阴影效果在多端的一致性,避免出现鸿蒙设备上阴影不显示、边缘模糊等问题。此外,游戏图片采用width: '100%'的自适应宽度设计,高度固定为180px,既保证了图片的显示比例,又避免了图片在不同设备上的拉伸问题。

组件内部的细节处理也充分考虑了鸿蒙跨端适配需求,例如,游戏标签的渲染采用flexWrap: 'wrap’的换行布局,可确保当标签数量较多时,在鸿蒙设备上能自动换行,避免出现标签溢出、排版错乱等问题;下载按钮与分享按钮采用TouchableOpacity组件实现触摸交互,该组件在鸿蒙系统中可自动适配原生触摸反馈规范,点击时呈现透明度变化的反馈效果,与鸿蒙原生组件的交互体验保持一致,避免出现点击无反馈、反馈生硬等问题,提升用户交互体验。

除了GameCard组件,页面中还隐含了多个可复用的小型组件逻辑,例如头部的用户按钮、搜索栏、标签页选项、底部导航项等,这些元素虽然未封装为独立的组件,但通过StyleSheet集中管理样式,实现了样式的复用,后续若需扩展页面或新增类似元素,可直接复用相关样式与逻辑,大幅提升开发效率,同时确保鸿蒙跨端视觉与交互的一致性。


对于RN鸿蒙跨端开发而言,细节处理直接决定了页面的适配效果,尤其对于内容展示类页面,布局、样式、交互等细节的适配不当,极易影响用户体验。本次热门游戏推荐页面的代码,在鸿蒙适配细节上做了充分的优化,规避了RN鸿蒙跨端开发中的常见坑点,确保页面在鸿蒙设备上的显示与交互效果,与iOS、Android设备完全一致。

首先是布局适配细节,除了前文提到的SafeAreaView与Dimensions组件的运用,页面还针对横向滚动组件做了适配优化。标签页模块采用ScrollView组件实现横向滚动,设置showsHorizontalScrollIndicator={false}隐藏横向滚动条,同时将标签页容器设置为flexDirection: 'row’的弹性布局,确保标签页在鸿蒙设备上可正常横向滚动,避免出现滚动卡顿、滚动无响应等问题。需要注意的是,鸿蒙系统中,RN的ScrollView组件的横向滚动机制与原生一致,但需确保父容器与子容器的布局逻辑合理,避免出现滚动区域异常的问题,本次代码中通过设置tabsWrapper容器的flexDirection: ‘row’,完美规避了这一坑点。

其次是样式适配细节,代码中通过StyleSheet.create集中管理所有组件的样式,避免了inline样式的使用——这是RN鸿蒙跨端开发的重要适配技巧。鸿蒙系统中,inline样式可能出现渲染延迟、样式失效、重渲染性能下降等问题,而集中式样式管理不仅便于维护和修改,还能减少鸿蒙系统样式渲染的异常。例如,所有卡片组件的阴影样式、圆角样式,所有文本的字体大小、颜色,所有按钮的样式,均通过StyleSheet集中定义,后续若需调整样式,只需修改对应样式属性,即可同步生效,无需修改组件内部代码,同时确保样式在鸿蒙多设备上的一致性。

在字体与颜色适配方面,代码也做了细致的处理,贴合鸿蒙原生视觉规范。字体大小采用固定像素值(如12px、14px、16px、18px),但这些像素值均为RN的相对像素值,可适配鸿蒙设备的字体缩放功能——当用户调整鸿蒙设备的字体大小时,页面中的所有文本会同步缩放,避免出现文字溢出、排版错乱、可读性下降的问题。颜色搭配采用鸿蒙原生应用常用的配色方案,主色调采用#3b82f6(蓝色),辅助色采用#f1f5f9(浅灰色),文本颜色采用#1e293b(标题)、#64748b(正文)、#94a3b8(辅助文本),对比度合理,确保在鸿蒙设备上的可读性,同时避免使用平台特定的颜色属性,确保颜色在多端的一致性。

图片渲染适配也是本次代码的亮点之一,游戏图片采用Image组件加载网络图片,通过uri属性指定图片地址,RN框架会自动适配鸿蒙系统的图片渲染机制,无需额外编写适配代码。需要注意的是,鸿蒙系统中,网络图片的加载需要确保APP拥有网络权限,本次代码虽未涉及权限配置,但在实际跨端开发中,需在鸿蒙工程的配置文件中添加网络权限,避免出现图片加载失败的问题。此外,代码中图片采用固定高度、自适应宽度的设计,确保图片在不同宽度的鸿蒙设备上,均能保持清晰的显示效果,不出现模糊、拉伸等问题。

最后是交互适配细节,页面中的所有触摸交互均采用RN官方的TouchableOpacity组件,避免使用第三方交互组件——第三方组件往往存在鸿蒙适配不完善的问题,容易导致交互异常。TouchableOpacity组件在鸿蒙系统中可自动适配原生触摸反馈,点击时的透明度变化与鸿蒙原生组件保持一致,同时确保点击区域准确,避免出现点击错位、点击无响应等问题。此外,弹窗提示采用RN官方的Alert组件,该组件在鸿蒙系统中会自动映射为鸿蒙原生弹窗,弹窗的按钮布局、文字样式、交互逻辑与鸿蒙原生弹窗保持一致,避免出现弹窗样式突兀、无法关闭等问题,确保用户在鸿蒙设备上的交互体验与原生应用一致。


热门游戏推荐页面的交互逻辑相对简洁,核心包括标签页切换、游戏下载、游戏分享、底部导航切换(预留)等场景,状态管理采用React Hooks(useState)实现,无需引入复杂的第三方状态管理库(如Redux、MobX),既简化了代码,又确保了跨端复用性——鸿蒙系统中,React Hooks的运行机制与RN原生环境完全一致,无需任何修改即可正常工作。

代码中通过useState钩子定义了两个核心状态:games状态用于存储热门游戏的模拟数据,初始化时赋值为HOT_GAMES数组,该状态为只读状态(未设置setGames方法),后续可扩展为接口请求获取数据,适配实际业务场景;activeTab状态用于管理当前激活的标签页,默认值为’热门’,通过setActiveTab方法实现标签页的切换,当用户点击不同的标签页(热门、新游、免费、付费)时,更新activeTab状态,从而切换标签页的激活样式,这种状态管理方式简洁高效,贴合标签页切换的核心需求。

交互逻辑的实现均基于RN官方API,且可无缝适配鸿蒙系统。例如,游戏下载与分享功能,通过定义handleDownload与handleShare两个回调函数,接收游戏ID参数,找到对应的游戏数据,然后通过Alert.alert方法弹出弹窗提示,告知用户当前操作的游戏名称。Alert组件在鸿蒙系统中的适配效果前文已详细说明,这里需要补充的是,弹窗的文本内容、按钮数量均可灵活调整,本次代码中采用单按钮弹窗,后续可根据业务需求扩展为双按钮弹窗(如确认下载、取消下载),且无需修改适配代码,即可在鸿蒙设备上正常显示。

标签页切换逻辑的实现的也较为简洁,通过map方法循环渲染tabs数组中的标签项,为每个标签项绑定TouchableOpacity组件的onPress事件,点击时调用setActiveTab方法更新activeTab状态,同时通过条件样式(activeTab === tab && styles.activeTab)切换标签项的激活样式,实现标签页的视觉切换。这种逻辑实现方式简洁易懂,且可灵活扩展标签项数量,后续若需新增标签页(如“单机”“网游”),只需修改tabs数组即可,无需修改核心逻辑,同时确保在鸿蒙设备上的切换流畅无卡顿。

底部导航的交互逻辑目前处于预留状态,通过TouchableOpacity组件实现导航项的触摸交互,默认激活“首页”导航项,后续可扩展为点击切换页面的逻辑,结合activeTab状态的思路,实现底部导航与页面内容的联动,且该逻辑可无缝适配鸿蒙系统,无需额外编写适配代码。


通过对热门游戏推荐页面代码的详细解读,我们可以总结出RN鸿蒙跨端内容展示类页面的核心开发思路:以RN官方核心API为基础,采用“模块化布局、组件化封装、简洁状态管理”的设计理念,重点关注布局自适应、样式一致性、交互流畅性三大核心要点,细致处理鸿蒙适配细节,规避常见坑点,即可实现“一次开发、多端复用”,高效开发出兼容iOS、Android、鸿蒙三端的页面。

本次解读的代码,虽然业务逻辑相对简洁,但涵盖了RN鸿蒙跨端内容展示类页面的所有核心技术点,包括布局适配、组件封装、图片渲染、触摸交互、弹窗提示等,其适配思路与代码设计可直接迁移到其他内容展示类页面(如新闻列表、商品推荐、视频列表等)的跨端开发中,具有较高的参考价值。同时,代码未引入任何第三方依赖,确保了跨端复用性与可维护性,符合鸿蒙跨端“低侵入、高复用、多端一致”的核心需求。

结合本次实践,给开发者提供几点RN鸿蒙跨端内容展示类页面的开发建议,帮助大家少走弯路、提升开发效率。首先,优先使用RN官方API与组件,避免引入第三方依赖——第三方组件往往存在鸿蒙适配不完善的问题,容易导致页面样式错乱、交互异常,而RN官方API与组件均已实现鸿蒙适配,可确保多端一致性,同时便于后续的维护与扩展。

其次,注重组件化封装与样式复用,对于页面中的重复元素(如卡片、列表项、按钮),尽量封装为独立的函数式组件,通过props实现数据与交互的传递,提升代码复用率;同时,通过StyleSheet集中管理样式,避免inline样式的使用,确保样式在多端的一致性,降低适配成本。


真实演示案例代码:








// app.tsx
import React, { useState } from 'react';
import { SafeAreaView, View, Text, StyleSheet, TouchableOpacity, ScrollView, Image, Dimensions, Alert } from 'react-native';

// 图标库
const ICONS = {
  home: '🏠',
  game: '🎮',
  star: '⭐',
  heart: '❤️',
  search: '🔍',
  download: '📥',
  share: '📤',
  user: '👤',
};

const { width } = Dimensions.get('window');

// 模拟热门游戏数据
const HOT_GAMES = [
  {
    id: 1,
    title: '王者荣耀',
    category: 'MOBA',
    developer: '腾讯游戏',
    rating: 4.8,
    releaseYear: 2015,
    price: '免费',
    image: 'https://picsum.photos/300/200?random=1',
    description: '公平竞技MOBA手游,经典英雄,极致对战体验',
    tags: ['5V5', '竞技', '团队'],
    downloads: '1亿+',
    size: '4.2GB'
  },
  {
    id: 2,
    title: '原神',
    category: 'RPG',
    developer: '米哈游',
    rating: 4.7,
    releaseYear: 2020,
    price: '免费',
    image: 'https://picsum.photos/300/200?random=2',
    description: '开放世界冒险游戏,精美画面,丰富剧情',
    tags: ['开放世界', '冒险', '二次元'],
    downloads: '5000万+',
    size: '8.1GB'
  },
  {
    id: 3,
    title: '和平精英',
    category: '射击',
    developer: '腾讯光子',
    rating: 4.6,
    releaseYear: 2019,
    price: '免费',
    image: 'https://picsum.photos/300/200?random=3',
    description: '战术竞技射击手游,百人同场竞技',
    tags: ['大逃杀', '射击', '战术'],
    downloads: '8000万+',
    size: '1.9GB'
  },
  {
    id: 4,
    title: '崩坏:星穹铁道',
    category: 'RPG',
    developer: '米哈游',
    rating: 4.9,
    releaseYear: 2023,
    price: '免费',
    image: 'https://picsum.photos/300/200?random=4',
    description: '银河冒险RPG,全新世界观,策略战斗',
    tags: ['回合制', '科幻', '剧情'],
    downloads: '1000万+',
    size: '6.7GB'
  },
  {
    id: 5,
    title: '英雄联盟手游',
    category: 'MOBA',
    developer: '腾讯游戏',
    rating: 4.5,
    releaseYear: 2021,
    price: '免费',
    image: 'https://picsum.photos/300/200?random=5',
    description: '端游经典移植,还原PC版体验',
    tags: ['经典', 'MOBA', '竞技'],
    downloads: '3000万+',
    size: '3.8GB'
  },
  {
    id: 6,
    title: '阴阳师',
    category: '卡牌',
    developer: '网易游戏',
    rating: 4.4,
    releaseYear: 2016,
    price: '免费',
    image: 'https://picsum.photos/300/200?random=6',
    description: '和风卡牌收集RPG,精美画风,深度养成',
    tags: ['和风', '卡牌', '收集'],
    downloads: '5000万+',
    size: '2.1GB'
  }
];

const GameCard: React.FC<{ 
  game: any, 
  onDownload: (id: number) => void,
  onShare: (id: number) => void
}> = ({ game, onDownload, onShare }) => {
  return (
    <View style={styles.gameCard}>
      <Image source={{ uri: game.image }} style={styles.gameImage} />
      <View style={styles.gameInfo}>
        <View style={styles.gameHeader}>
          <Text style={styles.category}>{game.category}</Text>
          <Text style={styles.rating}>评分: {game.rating}</Text>
        </View>
        <Text style={styles.title}>{game.title}</Text>
        <Text style={styles.developer}>开发商: {game.developer}</Text>
        <Text style={styles.description}>{game.description}</Text>
        <View style={styles.statsRow}>
          <Text style={styles.stat}>下载量: {game.downloads}</Text>
          <Text style={styles.stat}>大小: {game.size}</Text>
        </View>
        <View style={styles.tagsRow}>
          {game.tags.map((tag: string, index: number) => (
            <View key={index} style={styles.tag}>
              <Text style={styles.tagText}>{tag}</Text>
            </View>
          ))}
        </View>
        <View style={styles.cardFooter}>
          <TouchableOpacity style={styles.downloadButton} onPress={() => onDownload(game.id)}>
            <Text style={styles.downloadIcon}>{ICONS.download}</Text>
            <Text style={styles.downloadText}>下载</Text>
          </TouchableOpacity>
          <TouchableOpacity style={styles.shareButton} onPress={() => onShare(game.id)}>
            <Text style={styles.shareIcon}>{ICONS.share}</Text>
          </TouchableOpacity>
        </View>
      </View>
    </View>
  );
};

const HotGameRecommendPage: React.FC = () => {
  const [games] = useState(HOT_GAMES);
  const [activeTab, setActiveTab] = useState('热门');

  const tabs = ['热门', '新游', '免费', '付费'];

  const handleDownload = (id: number) => {
    const game = games.find(g => g.id === id);
    Alert.alert('下载', `开始下载游戏: ${game?.title}`);
  };

  const handleShare = (id: number) => {
    const game = games.find(g => g.id === id);
    Alert.alert('分享', `分享游戏: ${game?.title}`);
  };

  return (
    <SafeAreaView style={styles.container}>
      {/* 头部 */}
      <View style={styles.header}>
        <Text style={styles.title}>热门游戏推荐</Text>
        <TouchableOpacity style={styles.userButton}>
          <Text style={styles.userIcon}>{ICONS.user}</Text>
        </TouchableOpacity>
      </View>

      {/* 搜索栏 */}
      <View style={styles.searchContainer}>
        <TouchableOpacity style={styles.searchButton}>
          <Text style={styles.searchIcon}>{ICONS.search}</Text>
          <Text style={styles.searchText}>搜索游戏或开发商</Text>
        </TouchableOpacity>
      </View>

      {/* 标签页 */}
      <ScrollView horizontal showsHorizontalScrollIndicator={false} style={styles.tabsContainer}>
        <View style={styles.tabsWrapper}>
          {tabs.map(tab => (
            <TouchableOpacity 
              key={tab} 
              style={[styles.tab, activeTab === tab && styles.activeTab]}
              onPress={() => setActiveTab(tab)}
            >
              <Text style={[styles.tabText, activeTab === tab && styles.activeTabText]}>
                {tab}
              </Text>
            </TouchableOpacity>
          ))}
        </View>
      </ScrollView>

      {/* 主要内容 */}
      <ScrollView style={styles.content}>
        <Text style={styles.sectionTitle}>本周热门</Text>
        <Text style={styles.sectionSubtitle}>为你精选的优质游戏</Text>
        
        {games.map(game => (
          <GameCard 
            key={game.id} 
            game={game} 
            onDownload={handleDownload}
            onShare={handleShare}
          />
        ))}
      </ScrollView>

      {/* 底部导航 */}
      <View style={styles.bottomNav}>
        <TouchableOpacity style={styles.navItem}>
          <Text style={[styles.navIcon, styles.activeNavIcon]}>{ICONS.home}</Text>
          <Text style={[styles.navText, styles.activeNavText]}>首页</Text>
        </TouchableOpacity>
        <TouchableOpacity style={styles.navItem}>
          <Text style={styles.navIcon}>{ICONS.game}</Text>
          <Text style={styles.navText}>游戏</Text>
        </TouchableOpacity>
        <TouchableOpacity style={styles.navItem}>
          <Text style={styles.navIcon}>{ICONS.star}</Text>
          <Text style={styles.navText}>推荐</Text>
        </TouchableOpacity>
        <TouchableOpacity style={styles.navItem}>
          <Text style={styles.navIcon}>{ICONS.user}</Text>
          <Text style={styles.navText}>我的</Text>
        </TouchableOpacity>
      </View>
    </SafeAreaView>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#f8fafc',
  },
  header: {
    flexDirection: 'row',
    justifyContent: 'space-between',
    alignItems: 'center',
    padding: 20,
    backgroundColor: '#ffffff',
    borderBottomWidth: 1,
    borderBottomColor: '#e2e8f0',
  },
  title: {
    fontSize: 22,
    fontWeight: 'bold',
    color: '#1e293b',
  },
  userButton: {
    width: 40,
    height: 40,
    borderRadius: 20,
    backgroundColor: '#e2e8f0',
    justifyContent: 'center',
    alignItems: 'center',
  },
  userIcon: {
    fontSize: 20,
    color: '#64748b',
  },
  searchContainer: {
    padding: 16,
    backgroundColor: '#ffffff',
  },
  searchButton: {
    flexDirection: 'row',
    alignItems: 'center',
    backgroundColor: '#f1f5f9',
    borderRadius: 20,
    paddingHorizontal: 16,
    paddingVertical: 12,
  },
  searchIcon: {
    fontSize: 18,
    color: '#64748b',
    marginRight: 8,
  },
  searchText: {
    fontSize: 16,
    color: '#94a3b8',
    flex: 1,
  },
  tabsContainer: {
    backgroundColor: '#ffffff',
  },
  tabsWrapper: {
    flexDirection: 'row',
    paddingLeft: 16,
  },
  tab: {
    paddingHorizontal: 16,
    paddingVertical: 12,
    marginRight: 8,
  },
  activeTab: {
    borderBottomWidth: 2,
    borderBottomColor: '#3b82f6',
  },
  tabText: {
    fontSize: 16,
    color: '#64748b',
  },
  activeTabText: {
    color: '#3b82f6',
    fontWeight: '500',
  },
  content: {
    flex: 1,
    padding: 16,
  },
  sectionTitle: {
    fontSize: 24,
    fontWeight: 'bold',
    color: '#1e293b',
    marginBottom: 4,
  },
  sectionSubtitle: {
    fontSize: 14,
    color: '#64748b',
    marginBottom: 20,
  },
  gameCard: {
    backgroundColor: '#ffffff',
    borderRadius: 16,
    marginBottom: 20,
    overflow: 'hidden',
    elevation: 3,
    shadowColor: '#000',
    shadowOffset: { width: 0, height: 2 },
    shadowOpacity: 0.1,
    shadowRadius: 4,
  },
  gameImage: {
    width: '100%',
    height: 180,
  },
  gameInfo: {
    padding: 16,
  },
  gameHeader: {
    flexDirection: 'row',
    justifyContent: 'space-between',
    alignItems: 'center',
    marginBottom: 8,
  },
  category: {
    fontSize: 14,
    color: '#3b82f6',
    fontWeight: '500',
    backgroundColor: '#dbeafe',
    paddingHorizontal: 8,
    paddingVertical: 4,
    borderRadius: 12,
  },
  rating: {
    fontSize: 14,
    color: '#ef4444',
    fontWeight: 'bold',
  },
  title: {
    fontSize: 18,
    fontWeight: 'bold',
    color: '#1e293b',
    marginBottom: 4,
  },
  developer: {
    fontSize: 14,
    color: '#64748b',
    marginBottom: 6,
  },
  description: {
    fontSize: 14,
    color: '#64748b',
    lineHeight: 18,
    marginBottom: 12,
  },
  statsRow: {
    flexDirection: 'row',
    justifyContent: 'space-between',
    marginBottom: 10,
  },
  stat: {
    fontSize: 12,
    color: '#94a3b8',
  },
  tagsRow: {
    flexDirection: 'row',
    flexWrap: 'wrap',
    marginBottom: 16,
  },
  tag: {
    backgroundColor: '#f1f5f9',
    paddingHorizontal: 8,
    paddingVertical: 4,
    borderRadius: 12,
    marginRight: 8,
    marginBottom: 8,
  },
  tagText: {
    fontSize: 12,
    color: '#475569',
  },
  cardFooter: {
    flexDirection: 'row',
    justifyContent: 'space-between',
    alignItems: 'center',
  },
  downloadButton: {
    flexDirection: 'row',
    alignItems: 'center',
    backgroundColor: '#3b82f6',
    paddingHorizontal: 16,
    paddingVertical: 8,
    borderRadius: 20,
  },
  downloadIcon: {
    fontSize: 16,
    color: '#ffffff',
    marginRight: 4,
  },
  downloadText: {
    fontSize: 14,
    color: '#ffffff',
    fontWeight: '500',
  },
  shareButton: {
    padding: 8,
  },
  shareIcon: {
    fontSize: 20,
    color: '#64748b',
  },
  bottomNav: {
    flexDirection: 'row',
    justifyContent: 'space-around',
    backgroundColor: '#ffffff',
    borderTopWidth: 1,
    borderTopColor: '#e2e8f0',
    paddingVertical: 12,
  },
  navItem: {
    alignItems: 'center',
  },
  navIcon: {
    fontSize: 20,
    color: '#94a3b8',
    marginBottom: 4,
  },
  activeNavIcon: {
    color: '#3b82f6',
  },
  navText: {
    fontSize: 12,
    color: '#94a3b8',
  },
  activeNavText: {
    color: '#3b82f6',
  },
});

export default HotGameRecommendPage;

请添加图片描述


打包

接下来通过打包命令npn run harmony将reactNative的代码打包成为bundle,这样可以进行在开源鸿蒙OpenHarmony中进行使用。

在这里插入图片描述

打包之后再将打包后的鸿蒙OpenHarmony文件拷贝到鸿蒙的DevEco-Studio工程目录去:

在这里插入图片描述

最后运行效果图如下显示:

请添加图片描述
本文剖析了热门游戏推荐页面(HotGameRecommendPage)的跨端开发实践,该页面采用React Native函数组件架构,通过模块化设计实现iOS、Android和鸿蒙三端适配。文章从五个维度展开:

  • 组件化封装:GameCard组件实现游戏卡片的复用,采用props接收数据和回调函数,确保跨端一致性;
  • 状态管理:使用useState管理游戏列表和标签页状态,适配鸿蒙的@State装饰器;
  • 布局适配:通过SafeAreaView和Dimensions实现多设备自适应,Flexbox布局保证三端显示效果;
  • 交互实现:标签切换、下载分享等功能基于RN核心API开发,兼容鸿蒙事件机制;
  • 性能优化:组件拆分、样式复用等策略提升渲染效率。

该案例展示了如何通过RN官方API开发高复用性页面,为内容展示类应用的跨端开发提供参考模板,特别适合鸿蒙多形态设备的适配需求。

欢迎大家加入开源鸿蒙跨平台开发者社区,一起共建开源鸿蒙跨平台生态。

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐