GameBlackJack 组件采用了现代 React 函数组件架构,结合 useState Hook 实现了精细化的状态管理。组件通过多个状态变量控制不同的 UI 状态,包括当前选中的标签、页码、详情页显示状态、滚动位置、点赞记录和筛选标签等。这种状态分离设计使得组件逻辑清晰,易于维护和扩展。

在类型定义上,使用了 TypeScript 的 Item 接口明确数据结构,包含 idtitlesummaryimage 四个属性。这种类型定义在跨端开发中尤为重要,确保了在不同平台上的数据结构一致性,减少了类型错误的可能性。

图标系统

组件使用了 Base64 编码的图标资源,通过 ICONS 对象集中管理。这种资源管理方式在跨端开发中具有明显优势:

  1. 减少网络请求:Base64 编码的图标直接嵌入代码中,无需额外的网络请求,提高了应用加载速度。
  2. 跨平台兼容:避免了不同平台对资源文件格式和路径的差异,确保了图标在所有平台上的一致显示。
  3. 代码简洁:通过对象集中管理图标,使得代码更加模块化,易于维护。
  4. 性能优化:减少了应用的打包体积,特别是在图标数量较多的情况下。

视觉设计

应用采用了现代化的移动应用布局设计,主要包含以下几个部分:

  1. 头部区域:显示标题和操作按钮,支持根据滚动位置动态调整样式,如缩放效果和阴影透明度。
  2. 趋势卡片:通过水平 ScrollView 展示规则速览和下注流程等热门内容。
  3. 玩法指南:根据当前页码显示不同的玩法指南卡片,每张卡片包含标题、摘要、图标和操作按钮。
  4. 分页控制:通过按钮实现页面切换,显示当前页码信息。
  5. 标签筛选:通过可点击的标签实现内容筛选功能。

视觉设计上,使用了简洁明了的风格,通过不同的图标和样式区分不同的内容类型。动态样式(如 selectedTag==='玩法'&&styles.tagActive)实现了选中状态的视觉反馈,提升了用户体验。

用户体验

组件实现了丰富的交互功能,包括标签切换、页面切换、详情查看、点赞、收藏和分享等。这些交互功能的实现遵循了 React 的最佳实践,通过状态更新驱动 UI 变化,确保了交互的一致性和可靠性。

特别是滚动位置的记录和头部样式的动态调整,为用户提供了流畅的视觉体验。点击反馈通过 TouchableOpacity 实现,为用户提供了明确的操作反馈。收藏和分享功能通过 Alert.alert 提供操作反馈,增强了用户的操作信心。


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

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

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

  3. 资源管理:使用 Base64 编码的图标资源,避免了不同平台对资源文件格式和路径的差异。

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

  5. 类型定义:使用 TypeScript 类型定义,确保了在不同平台上的数据结构一致性。

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


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

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

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

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

  4. 资源管理:虽然 Base64 编码的图标在鸿蒙系统中也能使用,但鸿蒙系统有自己的资源管理机制,可以考虑使用鸿蒙的资源管理方式,提高应用的性能和可维护性。

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

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

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

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

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


在跨端应用开发领域,React Native(RN)凭借“一次编写,多端运行”的核心优势,成为连接前端与原生应用的重要桥梁,而鸿蒙系统作为新兴的分布式操作系统,其对RN跨端开发的兼容与适配,更是为开发者提供了更广阔的应用落地场景。本文将以一段21点游戏的RN代码为例,从跨端适配、组件封装、状态管理、样式设计四个核心维度,深入解读RN在鸿蒙系统上的跨端开发逻辑与技术细节,帮助开发者快速掌握RN鸿蒙跨端开发的核心要点。

本次解读的代码片段,是一个完整的21点游戏展示界面,包含首页导航、内容滚动、标签切换、详情展示、分页控制等核心交互,完全贴合移动端(含鸿蒙手机端)的交互习惯,同时兼顾了RN跨端开发的兼容性设计,所有技术实现均符合RN与鸿蒙系统的适配规范,可直接在鸿蒙设备上编译运行(需完成RN对鸿蒙的适配配置)。


React Native鸿蒙跨端开发的前提,是完成RN与鸿蒙系统的依赖适配,核心在于借助鸿蒙系统提供的RN适配层(如HarmonyOS React Native Adapter),实现RN API与鸿蒙原生API的映射,让RN代码能够被鸿蒙系统正确解析和渲染。从本次代码的依赖引入来看,完全遵循了RN跨端开发的规范,未引入任何平台专属的私有API,确保了代码的跨端可移植性。

代码开篇引入的核心依赖,涵盖了RN跨端开发的基础组件与核心API:


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

其中,React核心的useState钩子用于状态管理,无需额外适配鸿蒙系统——RN适配层会自动将其映射为鸿蒙系统可识别的状态管理逻辑;而SafeAreaView、View、Text等基础组件,是RN跨端开发的通用组件,鸿蒙系统通过适配层,将这些组件转化为自身的原生组件(如View对应鸿蒙的ComponentContainer,Text对应鸿蒙的Text组件),确保组件在鸿蒙设备上的渲染一致性。

特别需要注意的是Dimensions API的使用:const { width } = Dimensions.get('window');,该API用于获取设备屏幕宽度,是跨端适配的关键。在鸿蒙系统中,RN适配层会自动获取鸿蒙设备的屏幕参数,无需开发者单独编写鸿蒙专属的屏幕适配代码,即可实现“一套代码,适配不同尺寸鸿蒙设备”的效果,这也是RN跨端开发效率的核心体现。

此外,代码中引入的Image组件,支持base64格式的图片资源(如ICONS对象中定义的图片),这在跨端开发中尤为实用——鸿蒙系统与其他移动端系统一样,支持base64图片的直接渲染,无需为不同平台单独处理图片格式,避免了跨端开发中常见的图片适配问题。


状态管理是跨端应用的核心,无论是React Native还是鸿蒙系统的前端开发,都需要高效的状态管理方案来处理页面交互、数据更新等场景。本次代码采用React原生的useState钩子实现状态管理,完全兼容鸿蒙跨端场景,无需引入Redux、MobX等第三方状态管理库,简化了跨端开发的复杂度,同时保证了状态更新的高效性。

代码中定义的核心状态如下,每一个状态都对应着跨端界面的交互逻辑,且均遵循RN与鸿蒙的适配规范:

  • selectedTag:用于管理顶部标签的选中状态(玩法/筹码/结算),控制标签切换时的UI反馈,跨端场景下,标签切换的点击事件(onPress)会被鸿蒙适配层转化为原生点击事件,确保交互流畅性;

  • page:用于管理分页状态(1/2页),控制玩法指南内容的分页展示,分页切换逻辑(nextPage)无需区分平台,可直接在鸿蒙设备上正常运行;

  • detail:用于管理详情页的展示状态,控制点击游戏卡片后跳转至详情页的逻辑,其类型定义(Item | null)采用TypeScript语法,确保跨端开发的类型安全,避免因类型错误导致的平台适配问题;

  • scrollY:用于监听滚动视图的滚动距离,实现顶部导航栏的缩放(transform)和阴影透明度(shadowOpacity)动态变化,这一交互效果在鸿蒙系统中,通过RN适配层对原生滚动事件的监听,可实现与iOS、Android端一致的视觉体验;

  • likes:用于管理游戏卡片的点赞数量,采用对象格式存储(Record<string, number>),支持多卡片独立点赞计数,状态更新逻辑(like)通过展开运算符实现不可变数据更新,符合React最佳实践,同时兼容鸿蒙系统的状态更新机制;

  • chips:用于管理底部筹码标签的选中状态,支持标签的添加与删除(toggleChip),其交互逻辑完全通用,无需为鸿蒙系统单独适配。

值得注意的是,RN的状态更新是异步的,这一特性在鸿蒙系统中同样适用,开发者无需担心状态更新顺序导致的UI错乱问题。同时,TypeScript的使用的(如Item类型定义),不仅提升了代码的可维护性,也为鸿蒙跨端开发提供了类型校验,避免了因平台差异导致的类型不兼容问题,这也是RN跨端开发中推荐的实践方式。


React Native鸿蒙跨端开发的核心优势之一,就是组件的复用性——开发者可以编写一套通用组件,无需修改代码,即可在鸿蒙、iOS、Android等多平台上渲染展示。本次代码中,所有组件的封装均遵循RN通用组件规范,同时兼顾了鸿蒙系统的渲染特性,主要分为基础布局组件、交互组件、自定义组合组件三类,下面逐一解读其跨端适配逻辑。

3.1 基础布局组件:

代码中使用的SafeAreaView、View、ScrollView等基础布局组件,是RN跨端开发的核心布局载体,其在鸿蒙系统中的适配逻辑,由RN适配层自动完成,开发者无需额外处理,但需注意布局样式的通用性(如避免使用平台专属的布局属性)。

例如,SafeAreaView组件用于适配设备的安全区域(如鸿蒙手机的刘海屏、状态栏),确保内容不会被状态栏、导航栏遮挡,这一组件在鸿蒙系统中,会自动识别设备的安全区域参数,与iOS、Android端实现一致的适配效果;ScrollView组件分为垂直滚动(content)和水平滚动(trending),其showsHorizontalScrollIndicator={false}属性用于隐藏水平滚动条,在鸿蒙系统中同样生效,保证了跨端UI的一致性;View组件作为最基础的容器组件,用于包裹其他组件,其flex布局(如flexDirection、justifyContent、alignItems)完全兼容鸿蒙系统,开发者可直接使用RN的flex布局语法,实现鸿蒙设备上的灵活布局。

3.2 交互组件:

交互组件是跨端应用的灵魂,本次代码中使用的TouchableOpacity、Alert等交互组件,均为RN通用交互组件,其在鸿蒙系统中的交互效果,通过RN适配层映射为鸿蒙原生交互逻辑,确保跨端交互的一致性和流畅性。

TouchableOpacity组件用于实现点击反馈(如按钮、卡片的点击),其onPress属性定义点击事件,在鸿蒙系统中,点击时会产生轻微的透明度变化(与iOS、Android端一致),无需开发者单独编写反馈逻辑;Alert组件用于实现弹窗提示(如搜索、收藏、分享的弹窗),其API用法与RN原生完全一致,在鸿蒙系统中会渲染为鸿蒙原生弹窗样式,兼顾了平台特性与交互一致性。

3.3 组合组件:

本次代码中,通过组合基础组件,封装了多个可跨端复用的自定义组件,如顶部导航栏、趋势卡片、游戏卡片、详情页组件等,这些组件的封装遵循“高内聚、低耦合”的原则,无需修改代码即可在鸿蒙系统上复用,大幅提升了跨端开发效率。

例如,游戏卡片组件(通过map遍历items生成),由Image、Text、TouchableOpacity等基础组件组合而成,包含卡片头像、标签、标题、摘要、操作按钮(点赞、收藏、分享)等元素,其样式和交互逻辑完全通用,在鸿蒙设备上会自动适配屏幕尺寸,确保卡片布局的合理性;趋势卡片组件(trendingCard)用于展示规则速览、下注流程等核心信息,采用水平滚动布局,适配鸿蒙手机的屏幕宽度,同时保证了与其他平台的UI一致性。

此外,代码中通过条件渲染({!detail && …}、{detail && …})实现了首页与详情页的切换,这一逻辑在跨端场景下完全通用,鸿蒙系统会根据状态变化,高效渲染对应的页面内容,避免了平台专属的页面切换逻辑编写。


样式设计是跨端开发中最容易出现平台差异的环节,React Native提供的StyleSheet API,通过CSS-in-JS的方式编写样式,同时支持通过适配层映射为不同平台的原生样式,本次代码的样式设计,完全遵循RN StyleSheet规范,同时兼顾了鸿蒙系统的样式特性,实现了跨端样式的一致性。

4.1 样式变量封装:

代码中首先封装了palette样式变量,定义了全局通用的颜色主题,如背景色、导航栏颜色、主色调、文本颜色等:


const palette = { 
  bg:'#f7f8fc', 
  header:'#ffffff', 
  primary:'#2563eb', 
  text:'#111827', 
  muted:'#6b7280', 
  card:'#ffffff', 
  ad:'#dbeafe', 
  adText:'#1e40af' 
};

这种封装方式,不仅提升了代码的可维护性,也确保了跨端样式的一致性——鸿蒙系统与其他平台一样,支持RGB颜色值,无需为鸿蒙系统单独定义颜色变量。同时,全局颜色主题的统一,也让应用的视觉风格更加统一,提升了用户体验。

4.2 样式:

在样式编写中,代码充分考虑了鸿蒙设备的屏幕特性,采用了“弹性布局+动态尺寸”的适配方式,避免了固定尺寸导致的适配问题。

例如,galleryImage组件的宽度设置:width:(width-48)/3,通过屏幕宽度(width)动态计算图片宽度,确保在不同尺寸的鸿蒙设备上,三张图片能够均匀分布,无需单独适配不同屏幕尺寸;顶部导航栏的缩放效果(transform: [{ scale: Math.max(0.9, 1 - scrollY / 400) }]),通过监听滚动距离(scrollY)动态调整缩放比例,在鸿蒙系统中,RN适配层会将transform属性映射为鸿蒙原生的缩放动画,实现与其他平台一致的视觉效果。

此外,样式中的borderRadius、padding、margin等属性,均采用统一的数值规范,鸿蒙系统会自动将这些属性映射为原生样式,确保组件的圆角、内边距、外边距等样式与其他平台一致;elevation属性用于设置组件阴影(如trendingCard),在鸿蒙系统中,会渲染为原生阴影效果,兼顾了平台特性与视觉一致性。

本次解读的21点游戏RN代码,是一套标准的RN鸿蒙跨端开发实战案例,其核心逻辑围绕“通用化、可复用、高适配”展开,通过React Hooks实现状态管理,通过通用组件封装实现跨端复用,通过StyleSheet实现样式适配,无需修改核心代码,即可在鸿蒙系统上编译运行,充分体现了React Native“一次编写,多端运行”的核心优势。


真实演示案例代码:

import React, { useState } from 'react';
import { SafeAreaView, View, Text, StyleSheet, ScrollView, Dimensions, TouchableOpacity, Alert, Image } from 'react-native';
const { width } = Dimensions.get('window');
const ICONS = {
  chip: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAQAAAC1+jfqAAAAKUlEQVR42mNgYGBg+P//PwMDw2EwQGBgYGBgQxgYGBgYGAaMQAAQJmAfaYI5wAAAABJRU5ErkJggg==',
  card: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAQAAAC1+jfqAAAALElEQVR42mNgYGBg+P//PwMDw2EwQGBgYGBgQxgYGBgYGAaMQAApJ3z0Qq8VQkAAAAASUVORK5CYII=',
  ace: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAQAAAC1+jfqAAAAK0lEQVR42mNgYGBg+P//PwMDw2EwQGBgYGBgQxgYGBgYGAaMQAAoVkvQw8oT2sAAAAASUVORK5CYII=',
  dealer: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAQAAAC1+jfqAAAAKUlEQVR42mNgYGBg+P//PwMDw2EwQGBgYGBgQxgYGBgYGAaMQAA0bqU+9o1KwAAAABJRU5ErkJggg==',
  trophy: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAK1BMVEUAAP8ZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRk8kq5bAAAADXRSTlMAAQIDBAUGBwgJCGnHnAAAAD5JREFUGNNjYGBgYGLgZGJiYGBgEAVgYGBgYQkGQ2BiYGBgQmBiYGAwYGBgYQAFGhgYGRgYgQkAAwA9fQF5O3QKsgAAAABJRU5ErkJggg=='
};
type Item = { id: string; title: string; summary: string; image: string };
export default function GameBlackJack() {
  const [selectedTag, setSelectedTag] = useState('玩法');
  const [page, setPage] = useState(1);
  const [detail, setDetail] = useState<Item | null>(null);
  const [scrollY, setScrollY] = useState(0);
  const [likes, setLikes] = useState<Record<string, number>>({});
  const [chips, setChips] = useState<string[]>(['基础', '筹码', '结算']);
  const items1: Item[] = [
    { id: '1', title: '基本规则', summary: '21点的计分与发牌规则', image: ICONS.card },
    { id: '2', title: 'A的处理', summary: 'A可计1或11的策略', image: ICONS.ace },
    { id: '3', title: '庄家规则', summary: '庄家的停牌与补牌规则', image: ICONS.dealer }
  ];
  const items2: Item[] = [
    { id: '4', title: '筹码与下注', summary: '下注与赢取筹码展示', image: ICONS.chip },
    { id: '5', title: '胜利与结算', summary: '结算与奖励说明', image: ICONS.trophy }
  ];
  const items = page === 1 ? items1 : items2;
  const onSearch = () => Alert.alert('搜索', '当前标签: ' + selectedTag);
  const nextPage = () => setPage(page === 1 ? 2 : 1);
  const open = (i: Item) => setDetail(i);
  const back = () => setDetail(null);
  const like = (id: string) => setLikes({ ...likes, [id]: (likes[id] || 0) + 1 });
  const toggleChip = (name: string) => {
    if (chips.includes(name)) setChips(chips.filter(c => c !== name));
    else setChips([...chips, name]);
  };
  return (
    <SafeAreaView style={styles.container}>
      <View style={[styles.header, { transform: [{ scale: Math.max(0.9, 1 - scrollY / 400) }], shadowOpacity: Math.min(0.3, scrollY / 300) }]}><Text style={styles.title}>万能游戏库:21</Text><View style={styles.actions}><TouchableOpacity style={styles.searchBtn} onPress={onSearch}><Text style={styles.searchText}>搜索</Text></TouchableOpacity><TouchableOpacity style={styles.tagBtn} onPress={() => setSelectedTag('玩法')}><Text style={[styles.tagText, selectedTag==='玩法'&&styles.tagActive]}>玩法</Text></TouchableOpacity><TouchableOpacity style={styles.tagBtn} onPress={() => setSelectedTag('筹码')}><Text style={[styles.tagText, selectedTag==='筹码'&&styles.tagActive]}>筹码</Text></TouchableOpacity><TouchableOpacity style={styles.tagBtn} onPress={() => setSelectedTag('结算')}><Text style={[styles.tagText, selectedTag==='结算'&&styles.tagActive]}>结算</Text></TouchableOpacity></View></View>
      <ScrollView style={styles.content} onScroll={e => setScrollY(e.nativeEvent.contentOffset.y)} scrollEventThrottle={16}>
        <ScrollView horizontal showsHorizontalScrollIndicator={false} style={styles.trending}>
          <View style={styles.trendingCard}><Image source={{ uri: ICONS.card }} style={styles.trendingIcon} /><View style={styles.trendingBody}><Text style={styles.trendingTitle}>规则速览</Text><Text style={styles.trendingSub}>计分与发牌</Text></View></View>
          <View style={styles.trendingCard}><Image source={{ uri: ICONS.chip }} style={styles.trendingIcon} /><View style={styles.trendingBody}><Text style={styles.trendingTitle}>下注流程</Text><Text style={styles.trendingSub}>筹码管理</Text></View></View>
        </ScrollView>
        {!detail && (
          <View>
            <Text style={styles.section}>玩法指南</Text>
            {items.map(i => (
              <TouchableOpacity key={i.id} style={styles.card} onPress={() => open(i)}>
                <View style={styles.cardHead}><Image source={{ uri: i.image }} style={styles.cardImage} /><Text style={styles.cardTag}>游戏</Text></View>
                <Text style={styles.cardTitle}>{i.title}</Text>
                <Text style={styles.cardSummary}>{i.summary}</Text>
                <View style={styles.cardActions}><TouchableOpacity style={styles.btn} onPress={() => like(i.id)}><Text style={styles.btnText}>点赞 {likes[i.id] || 0}</Text></TouchableOpacity><TouchableOpacity style={styles.btn} onPress={() => Alert.alert('收藏', i.title)}><Text style={styles.btnText}>收藏</Text></TouchableOpacity><TouchableOpacity style={styles.btn} onPress={() => Alert.alert('分享', i.title)}><Text style={styles.btnText}>分享</Text></TouchableOpacity></View>
              </TouchableOpacity>
            ))}
            <View style={styles.pagination}><TouchableOpacity style={styles.pageBtn} onPress={nextPage}><Text style={styles.pageText}>{page===1?'下一页':'上一页'}</Text></TouchableOpacity><Text style={styles.pageInfo}>{page}</Text></View>
            <View style={styles.chipsRow}>
              <TouchableOpacity style={[styles.chip, chips.includes('基础') && styles.chipActive]} onPress={() => toggleChip('基础')}><Text style={[styles.chipText, chips.includes('基础') && styles.chipTextActive]}>基础</Text></TouchableOpacity>
              <TouchableOpacity style={[styles.chip, chips.includes('筹码') && styles.chipActive]} onPress={() => toggleChip('筹码')}><Text style={[styles.chipText, chips.includes('筹码') && styles.chipTextActive]}>筹码</Text></TouchableOpacity>
              <TouchableOpacity style={[styles.chip, chips.includes('结算') && styles.chipActive]} onPress={() => toggleChip('结算')}><Text style={[styles.chipText, chips.includes('结算') && styles.chipTextActive]}>结算</Text></TouchableOpacity>
            </View>
          </View>
        )}
        {detail && (
          <View>
            <View style={styles.detailHeader}><TouchableOpacity style={styles.backBtn} onPress={back}><Text style={styles.backText}>返回</Text></TouchableOpacity><Text style={styles.detailTitle}>{detail.title}</Text></View>
            <Image source={{ uri: detail.image }} style={styles.detailImage} />
            <Text style={styles.detailContent}>该详情描述21点的关键策略与交互反馈,包含翻牌动效与提示信息。</Text>
            <View style={styles.video}><Text style={styles.videoText}>演示视频 ▶︎</Text></View>
            <View style={styles.galleryRow}>
              <Image source={{ uri: ICONS.card }} style={styles.galleryImage} />
              <Image source={{ uri: ICONS.ace }} style={styles.galleryImage} />
              <Image source={{ uri: ICONS.chip }} style={styles.galleryImage} />
            </View>
          </View>
        )}
        <View style={styles.ad}><Text style={styles.adText}>广告位:牌类游戏技巧</Text></View>
      </ScrollView>
      <View style={styles.bottom}><TouchableOpacity style={styles.navItem} onPress={() => Alert.alert('首页','返回首页')}><Text style={styles.navIcon}>🏠</Text><Text style={styles.navText}>首页</Text></TouchableOpacity><TouchableOpacity style={styles.navItem} onPress={() => Alert.alert('合集','查看合集')}><Text style={styles.navIcon}>🃏</Text><Text style={styles.navText}>合集</Text></TouchableOpacity><TouchableOpacity style={styles.navItem} onPress={() => Alert.alert('我的','进入我的')}><Text style={styles.navIcon}>👤</Text><Text style={styles.navText}>我的</Text></TouchableOpacity></View>
    </SafeAreaView>
  );
}
const palette = { bg:'#f7f8fc', header:'#ffffff', primary:'#2563eb', text:'#111827', muted:'#6b7280', card:'#ffffff', ad:'#dbeafe', adText:'#1e40af' };
const styles = StyleSheet.create({
  container:{flex:1,backgroundColor:palette.bg},
  header:{padding:16,backgroundColor:palette.header,borderBottomWidth:1,borderBottomColor:'#e5e7eb',flexDirection:'row',justifyContent:'space-between',alignItems:'center'},
  title:{fontSize:20,fontWeight:'700',color:palette.text},
  actions:{flexDirection:'row',alignItems:'center'},
  searchBtn:{paddingHorizontal:12,paddingVertical:8,backgroundColor:'#e0f2fe',borderRadius:8,marginRight:8},
  searchText:{color:palette.primary,fontWeight:'600'},
  tagBtn:{marginLeft:6,paddingHorizontal:10,paddingVertical:6,backgroundColor:'#f1f5f9',borderRadius:16},
  tagText:{color:palette.muted},
  tagActive:{color:palette.primary,fontWeight:'700'},
  content:{padding:16},
  trending:{marginBottom:12},
  trendingCard:{flexDirection:'row',alignItems:'center',backgroundColor:'#fff',borderRadius:12,padding:10,marginRight:10,elevation:1},
  trendingIcon:{width:36,height:36,borderRadius:8,marginRight:10,backgroundColor:'#e5e7eb'},
  trendingBody:{},
  trendingTitle:{fontSize:14,fontWeight:'600',color:palette.text},
  trendingSub:{fontSize:12,color:palette.muted},
  section:{fontSize:18,fontWeight:'700',color:palette.text,marginVertical:12},
  card:{backgroundColor:palette.card,borderRadius:12,padding:12,marginBottom:12},
  cardHead:{flexDirection:'row',alignItems:'center'},
  cardImage:{width:48,height:48,borderRadius:8,marginRight:12,backgroundColor:'#e5e7eb'},
  cardTag:{paddingHorizontal:8,paddingVertical:4,borderRadius:12,backgroundColor:'#dbeafe',color:'#1e40af'},
  cardTitle:{fontSize:16,fontWeight:'600',color:palette.text,marginTop:8},
  cardSummary:{fontSize:13,color:palette.muted,marginVertical:6},
  cardActions:{flexDirection:'row'},
  btn:{marginRight:8,paddingHorizontal:10,paddingVertical:6,backgroundColor:'#f1f5f9',borderRadius:8},
  btnText:{color:palette.muted},
  pagination:{flexDirection:'row',alignItems:'center',justifyContent:'space-between',backgroundColor:'#f1f5f9',borderRadius:12,paddingHorizontal:12,paddingVertical:8},
  pageBtn:{paddingHorizontal:12,paddingVertical:6,backgroundColor:'#fff',borderRadius:8},
  pageText:{color:palette.primary,fontWeight:'600'},
  pageInfo:{color:palette.muted},
  chipsRow:{flexDirection:'row',marginTop:8},
  chip:{paddingHorizontal:10,paddingVertical:6,backgroundColor:'#f1f5f9',borderRadius:16,marginRight:8},
  chipActive:{backgroundColor:'#dbeafe'},
  chipText:{color:palette.muted},
  chipTextActive:{color:palette.primary,fontWeight:'600'},
  detailHeader:{flexDirection:'row',alignItems:'center',justifyContent:'space-between'},
  backBtn:{paddingHorizontal:12,paddingVertical:6,backgroundColor:'#e0f2fe',borderRadius:8},
  backText:{color:palette.primary,fontWeight:'600'},
  detailTitle:{fontSize:18,fontWeight:'700',color:palette.text},
  detailImage:{width:width-32,height:200,borderRadius:12,marginVertical:12,backgroundColor:'#e5e7eb'},
  detailContent:{fontSize:14,lineHeight:22,color:palette.muted},
  video:{height:160,borderRadius:12,backgroundColor:'#111827',alignItems:'center',justifyContent:'center',marginVertical:12},
  videoText:{color:'#fff',fontSize:16},
  galleryRow:{flexDirection:'row',marginVertical:8},
  galleryImage:{width:(width-48)/3,height:90,borderRadius:8,marginRight:8,backgroundColor:'#e5e7eb'},
  ad:{backgroundColor:palette.ad,borderRadius:12,padding:12,alignItems:'center',marginTop:12},
  adText:{color:palette.adText},
  bottom:{flexDirection:'row',justifyContent:'space-around',backgroundColor:'#fff',borderTopWidth:1,borderTopColor:'#e5e7eb',paddingVertical:10},
  navItem:{alignItems:'center'},
  navIcon:{fontSize:20,color:palette.muted},
  navText:{fontSize:12,color:palette.muted}
});

请添加图片描述


打包

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

在这里插入图片描述

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

在这里插入图片描述

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

请添加图片描述
本文以21点游戏React Native组件为例,剖析跨端开发的核心技术。该组件采用React函数式组件架构,通过useState实现精细化状态管理,并运用TypeScript确保类型安全。在跨端适配方面,组件通过基础组件选择、样式管理、Base64图标资源和Flexbox布局实现RN与鸿蒙系统的兼容性。文章重点分析了状态管理机制、组件复用策略和样式转换方案,并提供了将RN组件适配到鸿蒙系统时的8个关键注意事项,包括组件映射、样式转换和事件处理等。该案例展示了如何通过合理设计实现"一次编写,多端运行"的跨端开发目标。

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

Logo

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

更多推荐