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

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

资源管理

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

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

布局

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

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

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

用户体验

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

特别是滚动位置的记录和头部样式的动态调整,为用户提供了流畅的视觉体验。点击反馈通过 TouchableOpacity 实现,为用户提供了明确的操作反馈。


在 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 等组件映射到鸿蒙系统的对应组件。

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

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


本次实现的微动漫·名言语录专题应用是一款聚焦动漫垂直领域的语录类轻资讯产品,围绕动漫核心的角色语录、编剧摘录、名场面词句打造轻量化内容体系,覆盖垂直领域内容应用高频的标签分类、分页加载、详情跳转、点赞/收藏/分享互动、筛选标签、横向推荐、滚动动效、详情画廊等核心功能,同时贴合动漫语录类应用视觉清新化、内容轻量化、交互简洁化的品类特性。

应用基于React Native原生基础组件开发,引入TypeScript实现轻量类型约束,通过useState完成全量状态管理,全程遵循无第三方库依赖、样式全局归一、逻辑与视图分离、跨端无平台耦合的开发原则,依托react-native-harmony桥接层的成熟映射能力,可实现鸿蒙端零核心逻辑修改、轻量样式微调的低成本适配,核心状态管理、布局逻辑、交互事件100%复用,为动漫语录、二次元文案、垂直领域轻内容类应用的React Native鸿蒙跨端开发提供了可直接落地的技术参考与实操方案。

作为动漫垂直领域的轻内容应用典型案例,该实现充分发挥React Native快速开发、跨端兼容的技术优势,针对语录类应用内容碎片化、交互高频化、视觉简约化的核心诉求做了针对性设计。以下从整体架构与跨端友好设计内核、核心技术实现细节、鸿蒙跨端适配核心要点、垂直领域轻内容应用跨端开发最佳实践四个维度,深度解读代码的技术设计与鸿蒙跨端落地逻辑,突出动漫语录类应用的开发特色与React Native鸿蒙跨端的低成本实现思路。

动漫语录:

微动漫名言语录应用作为典型的动漫垂直领域轻内容产品,核心设计诉求是视觉风格贴合语录类内容的清新属性、内容模块碎片化、操作路径极简、布局自适应多设备,同时需保证跨端适配时修改范围高度收敛,核心业务逻辑与交互体验多端一致。本次实现遵循单组件全内聚、极致极简技术栈、主题风格品类化、状态轻量管理、样式与逻辑分离的核心设计原则,将应用整体封装为单个函数式组件,按内容展示逻辑拆分为动态头部导航区、横向精选推荐栏、语录库列表区、分页控件区、筛选标签区、语录详情区、广告位、底部导航区八大模块,所有模块均采用卡片式流式布局实现视觉与功能的隔离,通过ScrollView实现纵向/横向滚动适配不同设备屏幕,结合useState实现轻量状态管理覆盖所有标签切换、分页加载、详情跳转、点赞、筛选标签等交互需求,全程无复杂的组件嵌套与跨组件数据共享,所有视图渲染、样式设计、业务逻辑均收敛在组件内部。

这种设计方式既契合动漫语录类应用视觉清新、内容碎片化、操作简洁的品类特性——用户可快速完成标签切换、语录浏览、详情查看、点赞收藏分享等核心操作,无冗余交互流程,又严格遵循React Native鸿蒙跨端开发规范:单组件高内聚设计让跨端修改范围高度收敛,无跨组件逻辑依赖,桥接层解析与映射效率更高;卡片式流式布局让鸿蒙端适配可按模块独立微调,不影响整体应用的展示与交互效果;纯原生基础组件与通用API的使用,让桥接层可直接完成组件与API的映射,无需开发自定义桥接模块;TypeScript类型约束仅在开发阶段做类型校验,编译后为纯JS代码,不影响跨端运行。

全局主题常量palette

palette针对动漫语录类应用的清新文艺属性做了专属的青绿色系配色设计,同时按视觉用途做语义化命名,既贴合品类特性,又为跨端适配提供了唯一的样式调整入口:

  • 基础色:bg(页面背景,浅青#f0fdfa)、header(头部背景,纯白)、card(卡片背景,纯白)——浅青背景打造清新的视觉氛围,纯白卡片保证语录内容的可读性,符合语录类应用的视觉定位;
  • 品牌色:primary(主色,青绿#0d9488)——作为核心交互元素(选中标签、搜索按钮、分页按钮、卡片角标)的配色,实现视觉焦点的集中,青绿色贴合动漫语录类应用的清新、文艺化属性;
  • 文字色:text(主文字,深灰蓝#0f172a)、muted(副文字,中灰#64748b)——深灰蓝与中灰搭配,保证文字可读性,符合移动端视觉规范,主文字用于标题,副文字用于语录描述、说明,实现内容的视觉分层;
  • 功能色:ad/adText(广告背景/文字,淡青+深青)、边框色(淡青#99f6e4)——为广告模块、边框配置与主色相呼应的青色调,保证整体视觉风格的统一性,同时实现模块间的视觉区分。

这种品类化+语义化的全局主题管理,让跨端样式微调效率提升至极致——鸿蒙端若需贴合系统的“鸿蒙蓝”主题,仅需将primary的颜色值修改为鸿蒙系统主色调,即可实现全局品牌色的统一替换;若需适配鸿蒙端的深色模式,仅需新增一套深色主题常量,通过桥接层监听鸿蒙端的主题切换事件,实现主题色的动态切换,核心样式与布局逻辑无需任何修改。

StyleSheet.create:

本次实现通过StyleSheet.create创建所有基础样式,将布局属性(尺寸、内边距、外边距、Flex相关)、视觉属性(圆角、边框、背景色)、文字属性(字号、字重、颜色) 按模块归一化管理,如card(语录卡片基础样式)、section(章节标题样式)、btn(操作按钮样式)等,保证同类型组件的样式统一,提升代码复用率,同时针对语录类应用新增了三按钮横向布局、语录角标专属样式等个性化设计,且所有基础样式均为跨端通用。

归一化样式设计在动漫语录轻内容应用中体现的核心优势尤为明显:

  1. 内容展示一致性:所有语录卡片、横向推荐卡片均复用统一的卡片基础样式(圆角12、内边距12),保证碎片化语录内容展示的规整性,提升用户浏览体验,且基础样式为跨端通用,鸿蒙端可直接复用;
  2. 交互元素统一性:所有操作按钮(点赞、收藏、分享、返回、分页)均复用统一的按钮基础样式(圆角8、浅灰/淡青背景),所有筛选标签、头部标签均复用统一的标签样式(圆角16、内边距水平10/垂直6),实现交互元素的视觉统一,让用户形成操作记忆,提升轻内容应用的操作效率;
  3. 跨端样式逻辑复用StyleSheet.create的创建逻辑为RN原生实现,react-native-harmony桥接层已将其映射为鸿蒙的StyleSheet.create,样式属性的命名与使用方式完全一致,跨端时可直接复用所有基础样式,仅需对部分端侧特有样式(如阴影elevation)做轻量微调。
条件样式绑定:

动漫语录轻内容应用的操作反馈及时性与状态识别清晰度是提升用户体验的关键,本次实现通过条件样式绑定为头部标签、筛选标签实现了交互状态与视觉反馈的深度联动,且所有绑定逻辑均为跨端通用实现,鸿蒙端可直接复用:

  1. 头部标签选中态:当头部标签(名言/摘录)被选中时(selectedTag === '名言'),文字色变为主色(palette.primary)且字重加粗,未选中时为副文字色(palette.muted),让用户清晰感知当前选中的内容标签,符合轻内容应用内容分类清晰的需求;
  2. 筛选标签选中态:筛选标签(角色/编剧/场景)通过chips.includes('角色')判断选中状态,选中时背景色变为淡主色(#ccfbf1)、文字色变为主色且加粗,未选中时为浅灰背景、副文字色,实现筛选条件的视觉清晰反馈,同时支持多标签选中,贴合动漫语录应用按维度筛选内容的需求。

所有条件样式绑定均通过简单的三元表达式与数组包含判断实现,无复杂的样式计算,RN与ArkUI均原生支持该种样式绑定方式,跨端时可直接复用,无需修改绑定逻辑。

动态头部动效:

滚动联动动效是轻内容类应用提升沉浸式浏览体验的核心设计,本次实现基于ScrollViewonScroll事件,实现了头部导航缩放+阴影渐变的滚动联动动效,核心逻辑为滚动距离监听+样式动态计算,纯JS实现,无任何第三方动效库依赖,跨端可直接复用,鸿蒙端仅需保证onScroll事件的正常触发与样式属性的无缝映射。

核心实现逻辑为:通过ScrollViewonScroll事件监听纵向滚动距离scrollY,将scrollY作为参数动态计算头部的scale缩放比例与shadowOpacity阴影透明度——transform: [{ scale: Math.max(0.9, 1 - scrollY / 400) }]实现头部随滚动距离增加从1倍缩放到0.9倍,保证语录内容浏览时的视觉聚焦;shadowOpacity: Math.min(0.3, scrollY / 300)实现头部随滚动距离增加从0渐变到0.3的阴影,增强页面的层次感。同时设置scrollEventThrottle={16}保证滚动事件的触发频率与屏幕刷新率一致(60帧/秒),避免动效卡顿,提升体验流畅度。

该动效的核心优势在于:

  1. 纯JS实现,跨端通用:所有动效计算均为原生JS的数学计算,无任何端侧依赖,RN与鸿蒙桥接层均支持transform缩放与shadowOpacity阴影渐变,跨端可直接复用;
  2. 性能优化到位:通过Math.max/Math.min限制缩放比例与阴影透明度的取值范围,避免过度变形,同时scrollEventThrottle保证动效流畅度,无性能损耗;
  3. 体验贴合语录浏览:头部轻微缩放与阴影渐变不影响碎片化语录内容的浏览,同时提升了页面的动态感与层次感,契合轻内容应用的沉浸式浏览需求。

核心交互逻辑:

微动漫名言语录应用的核心业务逻辑围绕内容标签切换、语录列表浏览、详情跳转、点赞/收藏/分享、分页加载、筛选标签、搜索反馈展开,所有业务逻辑均为纯JS实现,无任何端侧依赖,跨端时可直接复用,若需扩展数据持久化、真实数据请求、内容筛选等能力,仅需对接跨端通用的存储/网络API,核心业务逻辑无需修改。

  1. 标签切换逻辑:通过头部标签的onPress事件更新selectedTag状态,实现名言/摘录标签的切换,结合条件样式绑定实现选中态的视觉反馈,核心逻辑为状态更新与样式联动,纯JS实现,跨端可直接复用;
  2. 分页加载逻辑:通过page状态控制展示items1/items2两组动漫语录相关模拟数据,点击分页按钮触发nextPage函数实现页码切换,核心逻辑为状态更新与数据切换,纯JS实现,跨端可直接复用,若需实现真实分页,仅需将模拟数据替换为网络请求的分页语录数据,核心切换逻辑不变;
  3. 详情跳转与返回逻辑:点击语录卡片触发open函数,更新detail为选中的Item对象,实现列表到详情的视图切换;点击详情页返回按钮触发back函数,重置detailnull,实现详情到列表的返回,核心逻辑为状态驱动的条件渲染,通过{!detail && <列表区>}{detail && <详情区>}实现视图切换,无路由依赖,轻量高效,跨端可直接复用;
  4. 点赞逻辑:点赞功能通过like函数更新likes对象(以语录ID为键,点赞数为值),实现点赞数的累加,核心逻辑为对象式状态管理,纯JS实现,跨端可直接复用,若需实现持久化,仅需将likes同步到跨端存储API即可;
  5. 收藏/分享逻辑:收藏与分享功能通过Alert实现操作反馈,核心逻辑为Alert.alert的调用,贴合轻内容应用的基础交互需求,react-native-harmony桥接层已将其映射为鸿蒙的AlertDialog.show,跨端可直接复用,若需实现真实收藏/分享,仅需在对应事件中对接跨端存储/分享API即可;
  6. 筛选标签逻辑:通过toggleChip函数实现筛选标签的添加/删除,判断标签是否在chips数组中,存在则删除,不存在则添加,核心逻辑为数组的增删操作,纯JS实现,跨端可直接复用,若需实现语录内容筛选,仅需根据chips数组过滤列表数据即可;
  7. 搜索与导航反馈逻辑:搜索按钮、底部导航的点击事件均通过Alert实现操作反馈,核心逻辑为Alert.alert的调用,跨端可直接复用,若需实现真实搜索,仅需在onSearch函数中添加语录搜索逻辑即可。

所有核心业务逻辑均围绕useState状态展开,通过状态更新驱动视图渲染,无复杂的逻辑嵌套与端侧依赖,这是垂直领域轻内容应用React Native鸿蒙跨端开发的核心设计思路,保证了多端核心逻辑的完全复用。

Flex布局:

动漫语录轻内容应用的典型布局特征是内容碎片化、模块扁平化、横向推荐、列表纵向、详情通栏,本次实现充分发挥RN Flex布局的灵活性,实现了轻内容类应用的八大高频布局,所有布局均为跨端通用实现,无任何平台特有代码,可直接映射为ArkUI的Flex布局,实现与RN端高度一致的展示效果,同时贴合动漫语录应用内容碎片化、操作便捷、视觉清新化的设计需求,新增了三按钮横向操作栏、语录角标头部栏等语录类应用专属布局。

  1. 动态头部导航布局:采用flexDirection: row+justifyContent: 'space-between'实现头部标题与操作区的左右两端对齐,操作区内部再通过flexDirection: row实现搜索按钮与标签的横向排列,贴合移动端头部导航的设计习惯,同时绑定滚动动效实现动态变化,跨端可直接复用布局逻辑;
  2. 横向精选推荐栏布局:通过ScrollView horizontal实现横向滚动推荐栏,隐藏横向滚动条(showsHorizontalScrollIndicator={false})提升视觉体验,内部卡片采用flexDirection: row实现图标与文字的横向排列,贴合轻内容应用的横向轻量推荐需求,该布局为跨端通用实现,鸿蒙端可直接复用;
  3. 语录库列表布局:采用纵向流式布局,每个语录卡片为独立的TouchableOpacity,点击可跳转详情,卡片内部采用flexDirection: row(角标头部区)+flexDirection: column(内容区)+flexDirection: row(三按钮操作区)实现碎片化语录内容的分层展示,无冗余元素,贴合动漫语录内容碎片化的需求,跨端可直接复用;
  4. 三按钮横向操作布局:在语录卡片底部采用flexDirection: row实现点赞、收藏、分享三按钮的横向等距排列,为语录类应用高频交互设计,按钮复用统一基础样式,保证视觉一致性,跨端可直接复用;
  5. 分页控件布局:采用flexDirection: row+justifyContent: 'space-between'实现分页按钮与页码信息的左右两端对齐,轻量简洁,无冗余设计,贴合轻内容应用的操作需求,跨端可直接复用;
  6. 筛选标签布局:采用flexDirection: row实现筛选标签的横向排列,标签为圆角胶囊式设计,贴合动漫语录应用按维度筛选内容的需求,跨端可直接复用;
  7. 详情页通栏布局:详情页采用通栏式轻量化布局,详情图片宽度适配设备屏幕(width: width - 32),文字、视频预览区、画廊区纵向流式排列,画廊区通过flexDirection: row实现三张图标/图片的等分布局(width: (width - 48) / 3),贴合轻内容应用的详情浏览需求,动态尺寸计算保证不同设备的适配性;
  8. 底部导航布局:采用flexDirection: row+justifyContent: 'space-around'实现底部导航的均匀分布,每个导航项为“emoji图标+文字”的纵向排列,轻量化设计贴合动漫应用的年轻化属性,同时图标选用与语录类内容匹配的💬,贴合品类特性,跨端可直接复用。

所有布局均采用Flex核心属性实现,结合Dimensions动态计算关键元素尺寸,无任何硬编码的像素值布局,保证不同尺寸设备、不同窗口尺寸下的布局自适应,贴合轻内容应用的多设备展示需求,同时RN与ArkUI的布局属性完全一致,跨端时可直接复用布局逻辑,仅需对部分样式属性(如阴影elevation)进行轻量微调,贴合鸿蒙端的设计规范。


本次实现引入TypeScript做轻量类型约束,核心为**Item数据类型定义详情项类型校验**,在开发阶段避免类型错误,提升代码健壮性与可维护性,同时TypeScript编译后生成的纯JS代码可直接在RN与鸿蒙桥接层中运行,无任何跨端兼容问题,不增加跨端适配成本。

核心类型约束实现:通过type Item = { id: string; title: string; summary: string; image: string }定义语录列表项的数据类型,限制id/title/summary/image的类型为字符串,避免开发阶段传入非预期类型的数据;同时对detail状态做类型校验(useState<Item | null>(null)),限制其值为Item类型或null,避免访问详情页时出现空值错误。

TypeScript在垂直领域轻内容应用跨端开发中的核心价值在于:

  1. 开发阶段错误拦截:提前拦截数据类型错误,避免因数据类型问题导致的端侧渲染错误,提升多端开发的稳定性;
  2. 代码可读性与可维护性提升:明确的数据类型定义让代码意图更清晰,便于团队协作与后续功能扩展,尤其适合轻内容应用的多端迭代开发;
  3. 无跨端兼容成本:TypeScript为编译型语言,编译后与纯JS代码无异,可直接在RN与鸿蒙桥接层中运行,无需任何端侧适配。

作为典型的动漫垂直领域轻内容产品,本次微动漫名言语录应用的实现全程遵循跨端友好原则,单组件高内聚设计让核心逻辑无跨端依赖,品类化全局主题色与Base64图标让资源跨端复用无成本,原生基础组件与Flex布局让桥接层无缝映射,模块化样式设计让鸿蒙端适配仅需轻量微调。依托react-native-harmony桥接层的成熟映射能力,该应用可实现鸿蒙端的零核心逻辑修改、轻量样式微调、快速适配,核心适配要点与实操方案如下,可复用于所有动漫语录、二次元文案、垂直领域轻内容类应用的鸿蒙跨端开发。

所有RN原生基础组件均通过桥接层无缝映射为ArkUI组件,组件的Props传值、事件绑定、布局逻辑、样式绑定完全复用,无需修改任何核心代码,核心映射关系与动漫语录轻内容应用的适配要点如下,完全贴合轻内容应用内容展示、滚动浏览、简洁交互的核心需求:

RN原生组件 ArkUI映射组件 动漫语录轻内容应用适配要点
SafeAreaView SafeArea 布局逻辑完全复用,仅需微调内边距贴合鸿蒙端的安全区域规范,保证动漫语录内容不被系统状态栏/导航栏遮挡,提升内容浏览的完整性
ScrollView ScrollView 纵向/横向滚动逻辑、onScroll事件、scrollEventThrottle属性无缝映射,头部滚动动效、横向推荐栏的滚动体验与RN端完全一致,可通过桥接层开启鸿蒙端特有滑动手势,提升动漫语录浏览的流畅性
TouchableOpacity Button+Gesture onPress事件自动映射为onClick事件,点击透明度反馈由桥接层实现,语录卡片、按钮、标签的点击交互无感知适配,保证动漫轻内容应用简洁操作的体验一致性
Image Image Base64图标加载逻辑完全复用,source={{ uri: Base64字符串 }}的使用方式与RN端一致,无本地图片,零适配成本,保证动漫应用小图标的视觉一致性
View/Text View/Text 核心布局与文字展示逻辑完全复用,样式属性(字号、字重、颜色、行高)无缝映射,保证动漫语录的文字可读性与布局规整性,内容展示无偏差

所有组件的核心Props均为跨端通用,无需修改,仅需对部分组件的次要Props(如elevation阴影、borderRadius圆角)进行轻量微调,贴合鸿蒙端的组件规范,同时保留动漫语录应用清新化、轻量化的视觉特色。


真实演示案例代码:






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 = {
  quote: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAQAAAC1+jfqAAAAKUlEQVR42mNgYGBg+P//PwMDw2EwQGBgYGBgQxgYGBgYGAaMQAAGgFDE8s7KAAAAABJRU5ErkJggg==',
  pen: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAQAAAC1+jfqAAAALElEQVR42mNgYGBg+P//PwMDw2EwQGBgYGBgQxgYGBgYGAaMQAA1lCkH1rYkzsAAAAASUVORK5CYII=',
  star: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAL1BMVEUAAP8ZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRlYI3e6AAAAD3RSTlMAAQIDBAUGBwgJCgsMZqw2UAAAAEVJREFUGNNjYGBgYGLgYGAQWBiYmJgYGBgYGBgQmBiYGBgYQYwYGBgYQYgYGBgYgYgQGBgYGBgAAABf8gH9QjXQ8QAAAABJRU5ErkJggg=='
};
type Item = { id: string; title: string; summary: string; image: string };
export default function AnimeQuotes() {
  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: '角色经典台词收藏', image: ICONS.quote },
    { id: '2', title: '编剧摘录', summary: '编剧访谈中的金句', image: ICONS.pen }
  ];
  const items2: Item[] = [
    { id: '3', title: '名场面词句', summary: '场景中的经典描述', image: ICONS.star }
  ];
  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}>微动漫:名言语录</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></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.quote }} 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.pen }} 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}>该详情展示语录出处与情节衔接,并提供片段预览。</Text>
            <View style={styles.video}><Text style={styles.videoText}>片段预览 ▶︎</Text></View>
            <View style={styles.galleryRow}>
              <Image source={{ uri: ICONS.quote }} style={styles.galleryImage} />
              <Image source={{ uri: ICONS.star }} style={styles.galleryImage} />
              <Image source={{ uri: ICONS.pen }} 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:'#f0fdfa', header:'#ffffff', primary:'#0d9488', text:'#0f172a', muted:'#64748b', card:'#ffffff', ad:'#ccfbf1', adText:'#115e59' };
const styles = StyleSheet.create({
  container:{flex:1,backgroundColor:palette.bg},
  header:{padding:16,backgroundColor:palette.header,borderBottomWidth:1,borderBottomColor:'#99f6e4',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:'#ecfeff',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:'#ccfbf1',color:'#0d9488'},
  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:'#ccfbf1'},
  chipText:{color:palette.muted},
  chipTextActive:{color:palette.primary,fontWeight:'600'},
  detailHeader:{flexDirection:'row',alignItems:'center',justifyContent:'space-between'},
  backBtn:{paddingHorizontal:12,paddingVertical:6,backgroundColor:'#ecfeff',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:'#99f6e4',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工程目录去:

在这里插入图片描述

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

请添加图片描述
微动漫名言语录应用基于React Native函数组件开发,采用TypeScript类型约束和useState状态管理,实现标签切换、分页加载、点赞收藏等核心功能。应用通过StyleSheet.create集中管理样式,使用Flexbox布局和基础组件确保跨端兼容性,特别是鸿蒙系统的适配。设计上采用青绿色系主题和卡片式布局,符合动漫语录类应用清新简洁的特性。该实现展示了React Native在垂直领域轻内容应用开发中的优势,为跨平台适配提供了可复用的技术方案,只需轻量调整即可实现多端一致体验。

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

Logo

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

更多推荐