在React Native跨端开发体系中,轻量业务页面的组件化落地、静态资源的跨端兼容处理、模态层的通用实现是适配鸿蒙系统的核心技术要点,而二手置换的「我的发布」页面作为典型的展示型+轻交互型页面,覆盖了静态资源加载、列表展示、模态详情、多状态按钮交互等移动端常见能力,是验证React Native鸿蒙跨端适配可行性的优质载体。本次实现的SecondhandMyPosts页面基于React Native原生基础组件开发,全程使用TypeScript做类型约束,采用Base64格式管理本地小图标资源,无第三方原生库与复杂依赖,核心交互与渲染逻辑均为纯JS/TS实现。这种实现方式从底层契合了鸿蒙跨端的核心需求——Base64资源可跨端直接复用,原生基础组件能通过桥接层映射为ArkUI组件,纯JS逻辑无需修改即可在鸿蒙端运行。以下将从架构设计、核心功能实现、跨端友好型开发细节、鸿蒙端适配实操要点等维度,对该代码进行深度技术解读,挖掘展示型页面的React Native鸿蒙跨端开发思想与最佳实践。

作为二手置换模块的单一功能页面,SecondhandMyPosts遵循高内聚、低耦合的设计原则,采用「单组件+内部状态管理+内联样式」的轻量架构实现,未做过度的组件拆分,所有功能逻辑、视图渲染、状态管理均收敛在单个函数式组件中。这种架构设计对于展示型+轻交互型页面而言,既保证了代码的易维护性与可读性,又契合了React Native鸿蒙跨端的开发规范——单组件的高内聚实现让鸿蒙端适配的修改范围高度收敛,无需跨多个组件进行桥接与适配,大幅降低端侧改造成本

页面开篇通过ES6模块规范导入React核心Hooks(useState)与React Native原生基础组件,其中SafeAreaViewViewTextTouchableOpacityScrollViewImage为跨端通用的基础渲染组件,Alert为跨端通用的原生API,这些能力均已在华为开源的react-native-harmony桥接层中实现与鸿蒙ArkUI的一一映射,无需开发自定义桥接模块即可完成基础适配。全局层面抽离了ICONS_BASE64常量对象,将所有小图标资源统一转换为Base64格式进行管理,替代了传统的本地图片资源(如png/jpg)与第三方图标库,这是本次实现的核心跨端友好设计——传统本地图片资源在鸿蒙端需要适配ArkUI的资源目录规范,第三方图标库可能存在原生依赖,而Base64格式的图片以纯字符串形式存在,可在iOS、Android、鸿蒙多端直接复用,无需进行任何资源适配与转换,完美解决了小图标资源的跨端兼容问题。

页面的状态管理采用React内置的useState Hooks轻量实现,仅定义了detailVisible(详情模态层显隐状态)与detailTitle(详情页标题)两个状态,覆盖了模态层的核心交互需求,无复杂的状态流转与数据共享。所有交互回调函数(onPublishonDetailonCloseDetail)均为组件内部定义的纯函数,逻辑简洁且与平台无关,跨端时可直接复用。这种轻量的状态与逻辑设计,让页面的核心能力与原生平台完全解耦,成为跨端复用的核心资产。


本次实现的二手置换「我的发布」页面,核心覆盖了头部导航、发布物品列表、提示信息、操作按钮、模态详情层五大功能模块,所有模块的实现均基于React Native原生基础组件与跨端通用的开发方式,从布局、资源、交互、渲染四个维度践行了跨端友好型开发原则,其实现细节可直接复用于鸿蒙端,仅需做轻量的样式与API微调。

头部导航

页面头部采用SafeAreaView作为根容器,自动适配iOS、Android、鸿蒙设备的刘海屏、状态栏与导航栏,避免内容被系统组件遮挡,这是React Native跨端页面的基础布局规范,在鸿蒙端可通过react-native-harmony桥接层直接映射为ArkUI的SafeArea组件,实现端侧的系统适配。头部内部通过flexDirection: row+justifyContent: space-between实现标题与右侧图标区的左右分布,alignItems: center保证垂直居中,这种Flex弹性布局是React Native与ArkUI的通用布局方案,跨端可完全复用,无需修改布局逻辑。

右侧图标区结合了Image组件(加载Base64发布图标)与emoji表情(购物车),形成轻量的功能入口展示。其中Image组件通过source={{ uri: ICONS_BASE64.publish }}加载Base64资源,这是React Native加载Base64图片的标准方式,鸿蒙端的ArkUIImage组件同样支持Base64格式的uri加载,可直接复用该加载方式,无需修改资源引用逻辑;emoji表情以纯文本形式展示,跨端可直接复用,无需处理资源适配问题。头部的样式设计采用borderBottomWidthborderBottomColor实现与主体内容的视觉分隔,边框颜色选用与页面主题一致的暖黄色,贴合二手置换的产品调性,样式属性均为RN与ArkUI的通用属性,跨端可直接复用。

发布物品列表

发布物品列表是页面的核心展示模块,采用「分区容器+卡片式列表」的布局方式,适配移动端的视觉设计规范。列表外层通过View封装为独立分区,设置backgroundColorborderRadiusshadow实现卡片的视觉层级,其中shadow相关属性为React Native的跨端通用样式,鸿蒙端可通过桥接层映射为ArkUI的shadow属性,实现一致的阴影效果;分区内通过多个独立的card容器实现物品列表的纵向排列,每个卡片均为flexDirection: row的横向布局,包含「Base64图标+物品信息+查看按钮」三部分,满足展示与轻交互需求。

卡片内部的Image组件加载Base64物品图标,设置固定的宽高与圆角,同时添加浅背景色做占位,避免资源加载时的视觉空白,这种占位设计是移动端的通用体验优化方案,跨端可直接复用;物品信息区通过flex: 1占满卡片剩余宽度,实现不同设备的自适应,标题与副标题采用差异化的字体大小与颜色,提升信息层级;「查看」按钮采用轻量的标签式设计,通过backgroundColorborderRadius实现圆角标签效果,点击事件绑定onDetail回调,触发模态详情层的展示。所有卡片均添加了borderBottomWidth实现项间分隔,最后一个卡片的分隔线可通过条件渲染优化,本次实现为保持代码简洁采用统一添加,在轻量列表场景下无性能影响,跨端时可直接复用该布局方式。

提示信息

页面设置了差异化的提示信息分区与操作按钮区,实现了功能引导与核心操作的视觉区分,其样式设计与交互实现均遵循跨端通用原则。提示信息分区采用与主体列表不同的暖黄色背景,形成视觉差异化,内部通过两个tipRow容器展示提示内容,每个行容器均为「Base64信息图标+提示文本」的横向布局,图标与文本的间距通过marginRight控制,文本采用小字号浅灰色,符合移动端的提示信息设计规范。该分区的样式属性均为RN与ArkUI的通用属性,跨端时仅需根据鸿蒙设计规范微调背景色与圆角值即可,核心布局与渲染逻辑无需修改。

操作按钮区采用flexDirection: row实现「发布物品」与「批量管理」两个按钮的横向均分,通过flex: 1让按钮适配不同设备宽度,按钮间通过marginRight设置间距。两个按钮采用差异化的样式设计:普通按钮为浅灰色背景+深灰色文字,警告类按钮为暖黄色背景+橙棕色文字,通过样式区分按钮的功能类型,这是移动端的通用按钮设计规范。按钮内部结合Image(Base64图标)与Text实现图文混排,TouchableOpacity作为按钮的点击容器,提供统一的点击透明度反馈,这种实现方式在iOS、Android端表现一致,在鸿蒙端可通过桥接层映射为ArkUI的Button组件+Gesture手势,保证跨端交互体验的一致性。


作为典型的展示型+轻交互型页面,SecondhandMyPosts的实现全程遵循跨端友好型开发原则,Base64资源可直接复用,纯JS逻辑无需修改,原生基础组件可直接桥接,是React Native向鸿蒙端迁移的低成本案例。结合华为开源的react-native-harmony桥接层,该页面向鸿蒙端的适配可实现零逻辑修改、轻样式微调、快桥接映射,核心适配要点与实操方案如下,这些要点同样适用于其他React Native展示型页面的鸿蒙跨端开发。

1. 快速接入react-native-harmony

react-native-harmony是华为开源的React Native鸿蒙桥接层,实现了RN基础组件、通用API与鸿蒙ArkUI组件、鸿蒙原生API的一一映射,是RN应用向鸿蒙端迁移的核心工具。对于本页面而言,适配前仅需完成基础的桥接层环境搭建:将现有React Native项目接入鸿蒙开发工具DevEco Studio,安装react-native-harmony依赖,配置鸿蒙项目的package.jsonconfig.json文件,无需开发任何自定义桥接模块。因为页面仅使用了RN的基础组件与通用API,桥接层已提供成熟的映射方案,可直接实现基础的组件与API桥接。

2. Base64资源

页面中的所有小图标资源均为Base64格式,封装在ICONS_BASE64常量对象中,鸿蒙端可直接复用该常量对象与资源加载方式。ArkUI的Image组件与RN的Image组件一样,支持通过source={{ uri: Base64字符串 }}加载Base64格式的图片,无需进行任何资源转换与路径修改,仅需保证Base64字符串的正确性即可。这种资源管理方式让鸿蒙端的资源适配成本为零,是展示型页面小图标资源管理的最佳实践。

3. 基础组件

页面中使用的所有React Native基础组件,均可通过react-native-harmony桥接层无缝映射为鸿蒙ArkUI的同类组件,组件的Props传值、事件绑定、布局逻辑均可完全复用,无需修改核心代码,仅需对部分组件的属性名进行轻量映射(桥接层已自动完成):

  • 容器与布局组件:SafeAreaView→ArkUISafeAreaView→ArkUIViewScrollView→ArkUIScrollView,Flex布局逻辑完全复用;
  • 展示组件:Text→ArkUITextImage→ArkUIImage,文本渲染与Base64资源加载逻辑完全复用;
  • 交互组件:TouchableOpacity→ArkUIButton+GestureonPress事件自动映射为onClick事件,点击反馈逻辑由桥接层实现,保证跨端交互体验一致。

组件桥接是鸿蒙端适配的核心步骤,而本页面的纯基础组件使用方式,让桥接层可自动完成所有映射,无需开发者进行手动干预,实现了组件层的零代码修改。

4. 样式

RN的样式规范与ArkUI高度兼容,鸿蒙端的样式适配仅需根据鸿蒙系统设计规范进行局部微调,无需修改样式属性名与布局逻辑。鸿蒙系统对移动端应用的视觉设计有统一的规范,如更大的圆角值、更宽松的间距、更柔和的阴影效果、特定的主题色值等,针对本页面,仅需在StyleSheet.create中修改以下样式值即可:

  • 将所有卡片、按钮、面板的borderRadius从12/14调整为16(鸿蒙默认更大圆角);
  • 微调按钮的paddingVertical/paddingHorizontal,贴合鸿蒙按钮的间距规范;
  • 微调阴影的shadowOpacityshadowRadius,实现鸿蒙端更柔和的阴影效果;
  • 若需要贴合鸿蒙的系统主题,可微调背景色、文字色的色值,与鸿蒙系统的视觉风格保持一致。

样式微调为局部修改,收敛在styles对象中,不影响页面的核心渲染与交互逻辑,大幅提升适配效率。

5. 通用API

页面中使用的RN通用APIAlert.alert,在鸿蒙端可通过桥接层映射为ArkUI的AlertDialog.show() API,仅需轻量修改API的调用方式,无需修改业务逻辑。例如,页面中的onPublish回调中的Alert.alert('我的发布', '你已发布 3 个物品:台灯、书籍、运动鞋'),在鸿蒙端仅需修改为AlertDialog.show({ title: '我的发布', message: '你已发布 3 个物品:台灯、书籍、运动鞋' })即可,核心的弹窗触发逻辑与业务提示内容保持不变。

若页面中使用了其他RN通用API(如DimensionsAsyncStorage),同样可通过react-native-harmony提供的映射方案进行轻量替换,所有API替换均收敛在组件内部的回调函数中,修改范围高度收敛,不影响页面的核心逻辑。

6. 模态层

页面的模态层实现方式为RN与ArkUI的通用方案,核心布局与显隐逻辑可直接复用,针对鸿蒙端的特有交互体验,可进行轻量优化,提升端侧用户体验:

  • 鸿蒙端的手势导航与iOS/Android存在差异,可通过桥接层的SafeArea组件适配鸿蒙的手势导航区域,避免模态层内容被手势导航遮挡;
  • 鸿蒙端的按钮点击默认带有震动反馈,可结合鸿蒙的Vibration API为页面中的所有TouchableOpacity添加震动反馈,契合鸿蒙端的交互习惯;
  • 鸿蒙端支持深色模式,可结合鸿蒙的ColorMode API为页面添加深色模式适配,根据系统主题自动切换背景色、文字色与按钮色,提升端侧视觉体验。

本次基于React Native实现的二手置换「我的发布」页面,作为典型的展示型+轻交互型页面,全程践行了跨端友好型开发原则,通过Base64格式管理小图标资源、纯JS/TS实现核心逻辑、通用基础组件搭建视图、Flex弹性布局实现自适应,成为React Native鸿蒙跨端开发的最佳实践案例。从该页面的实现与适配解析中,可提炼出展示型页面的React Native鸿蒙跨端开发核心原则与实践启示,这些原则能有效降低展示型页面的鸿蒙适配成本,提升跨端开发效率:

  1. Base64格式管理本地小图标资源:对于尺寸小、数量少的本地图标,优先转换为Base64格式进行集中管理,避免本地资源目录的跨端适配成本,实现资源的一次编码、多端复用;
  2. 坚持纯JS/TS实现核心逻辑:展示型页面的状态管理、交互回调、条件渲染等核心逻辑,优先使用React内置Hooks与纯JS/TS实现,规避平台特有API与第三方原生库,让核心逻辑成为跨端复用的核心资产;
  3. 仅使用RN原生基础组件与通用API:全程使用RN的ViewTextImageTouchableOpacity等基础组件与AlertDimensions等通用API,这些能力已在react-native-harmony桥接层中实现与ArkUI的映射,无需开发自定义桥接模块;
  4. Flex弹性布局+自适应设计:采用Flex弹性布局搭建页面结构,避免硬编码像素值,通过flexpaddingmargin实现页面的自适应,适配不同尺寸的iOS、Android、鸿蒙设备,跨端无需修改布局逻辑;
  5. 样式遵循RN驼峰规范,贴合ArkUI兼容性:所有样式均采用RN驼峰命名法,使用RN与ArkUI的通用样式属性,鸿蒙端适配时仅需根据鸿蒙设计规范进行局部样式微调,无需修改样式属性名与布局逻辑;
  6. 高内聚的单组件实现轻量页面:对于展示型+轻交互型页面,采用单组件的高内聚实现方式,让鸿蒙端适配的修改范围高度收敛,无需跨多个组件进行桥接与适配。

这个二手置换应用的"我的发布"页面采用了清晰的组件化架构,通过单一组件 SecondhandMyPosts 实现了完整的功能。组件设计注重状态管理和用户交互,通过 useState Hook 管理详情面板的显示状态和当前查看的物品标题。

状态管理

const [detailVisible, setDetailVisible] = useState(false);
const [detailTitle, setDetailTitle] = useState<string | null>(null);

使用 useState Hook 管理两个核心状态:

  1. detailVisible:控制详情面板的显示/隐藏,初始值为 false
  2. detailTitle:存储当前查看的物品标题,初始值为 null

这种状态管理方式简洁明了,适合处理详情面板的显示和隐藏逻辑。


物品详情

const onDetail = (title: string) => {
  setDetailTitle(title);
  setDetailVisible(true);
};

const onCloseDetail = () => {
  setDetailVisible(false);
  setDetailTitle(null);
};

物品详情查看功能通过更新状态实现详情面板的显示和隐藏。当用户点击"查看"按钮时,会调用 onDetail 函数,设置物品标题并显示详情面板;当用户点击"关闭"按钮时,会调用 onCloseDetail 函数,隐藏详情面板并清空物品标题。

发布物品

const onPublish = () => Alert.alert('我的发布', '你已发布 3 个物品:台灯、书籍、运动鞋');

发布物品功能通过 Alert.alert 显示用户已发布的物品信息,提供了基本的用户反馈。

详情面板

{detailVisible && (
  <View style={styles.detailOverlay}>
    <View style={styles.detailPanel}>
      {/* 详情面板内容 */}
    </View>
  </View>
)}

详情面板通过条件渲染实现,当 detailVisibletrue 时显示。面板采用覆盖层的形式,包含物品标题、详细信息和操作按钮,提供了清晰的物品详情展示和交互功能。


页面布局

<SafeAreaView style={styles.container}>
  <View style={styles.header}>
    {/* 头部内容 */}
  </View>

  <ScrollView style={styles.content}>
    <View style={styles.section}>
      {/* 最近发布内容 */}
    </View>

    <View style={styles.sectionAlt}>
      {/* 小提示内容 */}
    </View>

    <View style={styles.actionBar}>
      {/* 操作按钮 */}
    </View>
  </ScrollView>

  {/* 详情面板 */}
</SafeAreaView>

页面布局采用了分层设计:

  • 头部:包含页面标题和操作图标
  • 内容区:使用 ScrollView 实现可滚动的内容区域,包含最近发布的物品、小提示和操作按钮
  • 详情面板:采用覆盖层的形式,显示物品的详细信息

这种布局设计清晰明了,用户可以直观地理解和使用页面的功能。

物品卡片设计

<View style={styles.card}>
  <Image source={{ uri: ICONS_BASE64.item }} style={styles.cardImg} />
  <View style={styles.cardText}>
    <Text style={styles.cardTitle}>台灯 · 八成新</Text>
    <Text style={styles.cardSub}>自取 · 价格可议</Text>
  </View>
  <TouchableOpacity onPress={() => onDetail('台灯 · 八成新')}>
    <Text style={styles.tag}>查看</Text>
  </TouchableOpacity>
</View>

物品卡片采用了左侧图片、中间文字、右侧操作按钮的布局结构,这种布局在列表展示类应用中非常常见,能够清晰地展示物品信息并提供基本的交互功能。卡片使用了统一的样式,确保了页面的一致性和美观度。


  1. 组件映射

    • SafeAreaViewSafeAreaFlex 容器
    • ViewFlex 容器
    • TextText 组件
    • ImageImage 组件
    • TouchableOpacityButtonText + 手势事件
    • ScrollViewScroll 组件
    • AlertDialog 组件
  2. 图片加载适配

    • React Native 中使用 source={{ uri: ICONS_BASE64.item }} 加载 Base64 编码的图片
    • 鸿蒙系统中可以使用类似的方式加载 Base64 编码的图片,语法可能略有不同
    • 对于网络图片,需要注意网络权限配置
  3. 样式适配

    • 鸿蒙系统的样式定义方式与 React Native 类似,但属性名称可能略有不同
    • 例如,shadow 相关属性在鸿蒙中需要使用 elevation 或其他等效属性
    • 尺寸单位在鸿蒙中默认使用 vp,与 React Native 的密度无关像素概念类似
  4. 状态管理适配

    • React Native 中使用 useState Hook 管理状态
    • 鸿蒙系统中可以使用 @State 装饰器实现类似的状态管理
    • 对于复杂状态,可以使用鸿蒙的 AppStorageLocalStorage
  5. 事件处理适配

    • React Native 中使用 onPress 处理点击事件
    • 鸿蒙系统中可以使用 onClick 或其他等效属性处理点击事件

  1. 组件复用

    • 考虑将物品卡片、详情面板等拆分为独立的组件,提高代码的可维护性:
    const ItemCard = ({ item, onDetail }) => (
      <View style={styles.card}>
        {/* 卡片内容 */}
      </View>
    );
    
    const DetailPanel = ({ visible, title, onClose, onCollect, onContact }) => (
      visible && (
        <View style={styles.detailOverlay}>
          {/* 详情面板内容 */}
        </View>
      )
    );
    
  2. 图片优化

    • 对于 Base64 编码的图片,考虑使用更高效的图片加载方式,减少内存占用:
    // 可以考虑使用 require 加载本地图片
    <Image source={require('./assets/item.png')} style={styles.cardImg} />
    
  3. 类型定义

    • 使用接口定义数据类型,提高代码的可读性和类型安全性:
    interface Item {
      id: string;
      title: string;
      subtitle: string;
      description: string;
      condition: string;
      transactionMethod: string;
    }
    
  4. 可访问性

    • 添加 accessibilityLabel 属性,提高应用的可访问性:
    <TouchableOpacity 
      onPress={() => onDetail('台灯 · 八成新')}
      accessibilityLabel="查看台灯详情"
    >
      <Text style={styles.tag}>查看</Text>
    </TouchableOpacity>
    
  5. 动画效果

    • 添加简单的动画效果,提升用户体验:
    import { Animated } from 'react-native';
    
    const fadeAnim = useRef(new Animated.Value(0)).current;
    
    useEffect(() => {
      if (detailVisible) {
        Animated.timing(fadeAnim, {
          toValue: 1,
          duration: 300,
          useNativeDriver: true,
        }).start();
      }
    }, [detailVisible]);
    
    // 在样式中使用
    style={[styles.detailOverlay, { opacity: fadeAnim }]}
    

在将此应用迁移到鸿蒙系统时,需要注意以下几点:

  1. 组件转换

    • 使用鸿蒙 ArkUI 框架的组件体系,将 React Native 组件映射为对应的 ArkUI 组件
    • 保持组件树结构和逻辑不变,只替换具体的组件实现
  2. 样式系统

    • 鸿蒙的样式定义采用类似 CSS 的语法,但需要适应其特有的属性和单位
    • 可以创建样式工具函数,统一处理 React Native 和鸿蒙的样式差异
  3. 状态管理

    • 鸿蒙系统中可以使用 @State@Prop 等装饰器实现类似的状态管理
    • 对于跨组件通信,可以使用事件总线或全局状态管理方案
  4. 事件处理

    • 鸿蒙系统的事件处理机制与 React Native 类似,但语法可能不同
    • 例如,React Native 中使用 onPress,鸿蒙中可能使用 onClick 或其他等效属性
  5. 图片资源

    • 鸿蒙系统的图片加载机制与 React Native 类似,但需要注意 Base64 编码图片的处理方式
    • 本地图片资源需要遵循鸿蒙系统的资源管理规范
  6. 布局系统

    • 鸿蒙系统的布局系统基于 Flexbox,与 React Native 兼容
    • 对于覆盖层的实现,需要确保在鸿蒙中能正确工作

这个二手置换应用的"我的发布"页面展示了 React Native 跨端开发的核心技术要点,通过合理的组件设计、清晰的状态管理、直观的用户界面和完整的功能实现,为用户提供了一个功能齐全、体验良好的二手物品管理工具。在鸿蒙系统适配方面,通过组件映射、样式适配和状态管理调整,可以快速实现跨端迁移,保持功能和视觉效果的一致性。


真实演示案例代码:




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

const ICONS_BASE64 = {
  publish: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNgYAAAAAMAASsJTYQAAAAASUVORK5CYII=',
  item: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNgYAAAAAMAASsJTYQAAAAASUVORK5CYII=',
  edit: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNgYAAAAAMAASsJTYQAAAAASUVORK5CYII=',
  delete: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNgYAAAAAMAASsJTYQAAAAASUVORK5CYII=',
  info: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNgYAAAAAMAASsJTYQAAAAASUVORK5CYII=',
};

const SecondhandMyPosts: React.FC = () => {
  const [detailVisible, setDetailVisible] = useState(false);
  const [detailTitle, setDetailTitle] = useState<string | null>(null);
  const onPublish = () => Alert.alert('我的发布', '你已发布 3 个物品:台灯、书籍、运动鞋');
  const onDetail = (title: string) => {
    setDetailTitle(title);
    setDetailVisible(true);
  };
  const onCloseDetail = () => {
    setDetailVisible(false);
    setDetailTitle(null);
  };

  return (
    <SafeAreaView style={styles.container}>
      <View style={styles.header}>
        <Text style={styles.title}>二手置换 · 我的发布</Text>
        <View style={styles.headerIcons}>
          <Image source={{ uri: ICONS_BASE64.publish }} style={styles.headerIconImg} />
          <Text style={styles.headerEmoji}>🛒</Text>
        </View>
      </View>

      <ScrollView style={styles.content}>
        <View style={styles.section}>
          <Text style={styles.sectionTitle}>最近发布</Text>
          <View style={styles.card}>
            <Image source={{ uri: ICONS_BASE64.item }} style={styles.cardImg} />
            <View style={styles.cardText}>
              <Text style={styles.cardTitle}>台灯 · 八成新</Text>
              <Text style={styles.cardSub}>自取 · 价格可议</Text>
            </View>
            <TouchableOpacity onPress={() => onDetail('台灯 · 八成新')}>
              <Text style={styles.tag}>查看</Text>
            </TouchableOpacity>
          </View>
          <View style={styles.card}>
            <Image source={{ uri: ICONS_BASE64.item }} style={styles.cardImg} />
            <View style={styles.cardText}>
              <Text style={styles.cardTitle}>书籍 · 技术合集</Text>
              <Text style={styles.cardSub}>九成新 · 可换物</Text>
            </View>
            <TouchableOpacity onPress={() => onDetail('书籍 · 技术合集')}>
              <Text style={styles.tag}>查看</Text>
            </TouchableOpacity>
          </View>
          <View style={styles.card}>
            <Image source={{ uri: ICONS_BASE64.item }} style={styles.cardImg} />
            <View style={styles.cardText}>
              <Text style={styles.cardTitle}>运动鞋 · 42</Text>
              <Text style={styles.cardSub}>轻微磨损 · 诚意出</Text>
            </View>
            <TouchableOpacity onPress={() => onDetail('运动鞋 · 42码')}>
              <Text style={styles.tag}>查看</Text>
            </TouchableOpacity>
          </View>
        </View>

        <View style={styles.sectionAlt}>
          <Text style={styles.sectionTitle}>小提示</Text>
          <View style={styles.tipRow}>
            <Image source={{ uri: ICONS_BASE64.info }} style={styles.tipIcon} />
            <Text style={styles.tipText}>上传清晰图片与详细描述能提升交换成功率。</Text>
          </View>
          <View style={styles.tipRow}>
            <Image source={{ uri: ICONS_BASE64.info }} style={styles.tipIcon} />
            <Text style={styles.tipText}>标注自取/邮寄方式与参考价格,提升效率。</Text>
          </View>
        </View>

        <View style={styles.actionBar}>
          <TouchableOpacity style={styles.actionBtn} onPress={onPublish}>
            <Image source={{ uri: ICONS_BASE64.edit }} style={styles.actionIcon} />
            <Text style={styles.actionText}>发布物品</Text>
          </TouchableOpacity>
          <TouchableOpacity style={[styles.actionBtn, styles.actionBtnWarn]} onPress={onPublish}>
            <Image source={{ uri: ICONS_BASE64.delete }} style={styles.actionIcon} />
            <Text style={styles.actionTextWarn}>批量管理</Text>
          </TouchableOpacity>
        </View>
      </ScrollView>
      {detailVisible && (
        <View style={styles.detailOverlay}>
          <View style={styles.detailPanel}>
            <View style={styles.detailHeader}>
              <Text style={styles.detailTitle}>{detailTitle}</Text>
              <TouchableOpacity onPress={onCloseDetail}>
                <Text style={styles.detailClose}>关闭</Text>
              </TouchableOpacity>
            </View>
            <View style={styles.detailBody}>
              <View style={styles.detailRow}>
                <Image source={{ uri: ICONS_BASE64.item }} style={styles.detailIcon} />
                <Text style={styles.detailText}>成色说明:无明显缺陷,功能正常。</Text>
              </View>
              <View style={styles.detailRow}>
                <Image source={{ uri: ICONS_BASE64.info }} style={styles.detailIcon} />
                <Text style={styles.detailText}>交易方式:支持面交或快递到付。</Text>
              </View>
            </View>
            <View style={styles.detailFooter}>
              <TouchableOpacity style={styles.detailBtn} onPress={() => Alert.alert('收藏', '已收藏该物品')}>
                <Text style={styles.detailBtnText}>收藏</Text>
              </TouchableOpacity>
              <TouchableOpacity style={[styles.detailBtn, styles.detailBtnPrimary]} onPress={() => Alert.alert('联系卖家', '已发送联系请求')}>
                <Text style={styles.detailBtnTextPrimary}>联系卖家</Text>
              </TouchableOpacity>
            </View>
          </View>
        </View>
      )}
    </SafeAreaView>
  );
};

const styles = StyleSheet.create({
  container: { flex: 1, backgroundColor: '#fffefc' },
  header: { padding: 16, backgroundColor: '#ffffff', borderBottomWidth: 1, borderBottomColor: '#fde68a', flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center' },
  title: { fontSize: 18, fontWeight: 'bold', color: '#0f172a' },
  headerIcons: { flexDirection: 'row', alignItems: 'center' },
  headerEmoji: { fontSize: 18, marginLeft: 8 },
  headerIconImg: { width: 24, height: 24 },
  content: { padding: 16 },
  section: { backgroundColor: '#ffffff', borderRadius: 12, padding: 14, shadowColor: '#000', shadowOffset: { width: 0, height: 1 }, shadowOpacity: 0.08, shadowRadius: 2 },
  sectionAlt: { backgroundColor: '#fff7ed', borderRadius: 12, padding: 14, marginTop: 16 },
  sectionTitle: { fontSize: 16, fontWeight: 'bold', color: '#0f172a', marginBottom: 10 },
  card: { flexDirection: 'row', alignItems: 'center', paddingVertical: 10, borderBottomWidth: 1, borderBottomColor: '#f3f4f6' },
  cardImg: { width: 40, height: 40, borderRadius: 8, marginRight: 10, backgroundColor: '#fffbeb' },
  cardText: { flex: 1 },
  cardTitle: { fontSize: 13, fontWeight: '600', color: '#0f172a' },
  cardSub: { fontSize: 12, color: '#64748b', marginTop: 2 },
  tag: { fontSize: 11, color: '#b45309', backgroundColor: '#fde68a', paddingHorizontal: 8, paddingVertical: 4, borderRadius: 10 },
  tipRow: { flexDirection: 'row', alignItems: 'center' },
  tipIcon: { width: 22, height: 22, marginRight: 6 },
  tipText: { fontSize: 12, color: '#475569' },
  actionBar: { flexDirection: 'row', justifyContent: 'space-between', marginTop: 18 },
  actionBtn: { flex: 1, backgroundColor: '#f1f5f9', borderRadius: 12, paddingVertical: 12, flexDirection: 'row', justifyContent: 'center', alignItems: 'center', marginRight: 10 },
  actionBtnWarn: { backgroundColor: '#fef3c7', marginRight: 0 },
  actionIcon: { width: 16, height: 16, marginRight: 6 },
  actionText: { fontSize: 14, color: '#334155', fontWeight: '500' },
  actionTextWarn: { fontSize: 14, color: '#b45309', fontWeight: '600' },
  detailOverlay: { position: 'absolute', left: 0, right: 0, top: 0, bottom: 0, backgroundColor: 'rgba(0,0,0,0.25)', justifyContent: 'center', alignItems: 'center', padding: 16 },
  detailPanel: { width: '100%', maxWidth: 420, backgroundColor: '#ffffff', borderRadius: 14, padding: 14, shadowColor: '#000', shadowOffset: { width: 0, height: 2 }, shadowOpacity: 0.12, shadowRadius: 4 },
  detailHeader: { flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between' },
  detailTitle: { fontSize: 16, fontWeight: '700', color: '#0f172a' },
  detailClose: { fontSize: 12, color: '#b45309', backgroundColor: '#ffedd5', paddingHorizontal: 8, paddingVertical: 4, borderRadius: 10 },
  detailBody: { marginTop: 10 },
  detailRow: { flexDirection: 'row', alignItems: 'center', marginTop: 8 },
  detailIcon: { width: 18, height: 18, marginRight: 6 },
  detailText: { fontSize: 12, color: '#475569' },
  detailFooter: { flexDirection: 'row', justifyContent: 'flex-end', marginTop: 12 },
  detailBtn: { backgroundColor: '#f1f5f9', borderRadius: 10, paddingVertical: 8, paddingHorizontal: 12, marginRight: 8 },
  detailBtnPrimary: { backgroundColor: '#ffedd5' },
  detailBtnText: { fontSize: 12, color: '#334155', fontWeight: '600' },
  detailBtnTextPrimary: { fontSize: 12, color: '#b45309', fontWeight: '700' },
});

export default SecondhandMyPosts;

请添加图片描述


打包

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

在这里插入图片描述

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

在这里插入图片描述

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

请添加图片描述
React Native跨端开发适配鸿蒙系统的核心技术要点包括:轻量业务页面组件化、静态资源跨端兼容和模态层通用实现。二手置换「我的发布」页面作为典型展示型+轻交互型页面,采用React Native原生组件开发,全程使用TypeScript约束类型,以Base64格式管理本地小图标资源,无第三方原生库依赖。该实现方案完美契合鸿蒙跨端需求:Base64资源可复用,原生组件通过桥接层映射为ArkUI组件,纯JS逻辑无需修改即可运行。页面采用高内聚、低耦合的单组件架构,便于鸿蒙端适配时修改范围高度收敛。核心功能模块基于跨端通用开发方式实现,仅需轻量样式微调即可适配鸿蒙系统。通过华为开源的react-native-harmony桥接层,可实现零逻辑修改、快速组件映射的资源复用方案,为React Native展示型页面鸿蒙跨端开发提供了可复用的最佳实践。

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

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐