React Native鸿蒙跨平台实现SearchCard组件设计为高度可配置的通用组件,通过 props 接收搜索结果数据和三个回调函数
本文介绍了一个基于React Native的资讯类应用搜索结果页面实现方案。采用函数式组件和useState轻量状态管理,通过原生组件构建了包含智能搜索栏、搜索历史、资讯卡片和底部导航的标准页面结构。核心功能包括关键词搜索、历史记录管理、收藏/分享交互等,全部基于跨平台原生能力实现,无第三方依赖。特别设计了搜索关键词的双态展示逻辑,支持搜索结果与推荐内容的智能切换。该方案遵循组件化解耦原则,采用原
这个搜索结果页面采用了模块化的组件架构,通过清晰的职责分离实现了代码的复用性和可维护性。核心组件 SearchCard 作为独立的可复用单元,负责单个搜索结果的展示和交互,而 SearchResultPage 作为主容器,负责搜索功能、搜索历史管理和结果列表的渲染。
可复用 SearchCard 组件
const SearchCard: React.FC<{
result: any,
onBookmark: (id: number) => void,
onShare: (id: number) => void,
onPress: (id: number) => void
}> = ({ result, onBookmark, onShare, onPress }) => {
// 组件实现...
};
SearchCard 组件设计为高度可配置的通用组件,通过 props 接收搜索结果数据和三个回调函数:收藏、分享和点击详情。这种设计使得组件可以在不同场景中灵活使用,只需传入不同的参数即可实现不同的功能。组件内部包含了结果的图片、分类、标题、摘要、作者信息和操作按钮等完整的展示内容。
数据结构
const SEARCH_RESULTS = [
{
id: 1,
title: '科技发展新趋势:人工智能引领未来',
summary: '人工智能技术正在快速发展,为各行各业带来前所未有的变化和机遇。',
author: '张记者',
time: '2小时前',
category: '科技',
readTime: '5分钟',
image: 'https://picsum.photos/300/200?random=1',
comments: 24,
isBookmarked: false,
},
// 更多结果...
];
数据结构设计全面而详细,包含了文章的基本信息、内容摘要、作者信息、阅读时间、评论数和收藏状态等。这种结构化的数据设计为后续的功能扩展和数据管理提供了便利,同时也使得搜索功能的实现变得简单直接。
状态管理
const [results, setResults] = useState(SEARCH_RESULTS);
const [searchQuery, setSearchQuery] = useState('');
const [searchHistory, setSearchHistory] = useState(['科技', '教育', '健康']);
使用 useState Hook 管理三个状态:
results:搜索结果列表,初始值为模拟数据SEARCH_RESULTSsearchQuery:搜索查询,初始值为空字符串searchHistory:搜索历史,初始值为 [‘科技’, ‘教育’, ‘健康’]
这种状态管理方式简洁明了,适合处理用户交互产生的状态变化。
搜索功能
const handleSearch = (query: string) => {
if (query.trim() !== '') {
// 在实际应用中,这里应该调用API进行搜索
// 暂时过滤现有数据作为演示
const filtered = SEARCH_RESULTS.filter(item =>
item.title.toLowerCase().includes(query.toLowerCase()) ||
item.summary.toLowerCase().includes(query.toLowerCase()) ||
item.category.toLowerCase().includes(query.toLowerCase())
);
setResults(filtered);
// 添加到搜索历史
if (!searchHistory.includes(query)) {
setSearchHistory(prev => [query, ...prev.slice(0, 4)]);
}
} else {
setResults(SEARCH_RESULTS);
}
};
搜索功能通过 filter 方法实现,根据搜索查询过滤结果列表,支持按标题、摘要和分类进行搜索。同时,搜索功能还会将新的搜索查询添加到搜索历史中,并限制历史记录的数量为5条。这种实现方式模拟了真实应用中的搜索功能,为后续的API集成做好了准备。
交互
const handleBookmark = (id: number) => {
setResults(results.map(item =>
item.id === id ? { ...item, isBookmarked: !item.isBookmarked } : item
));
};
const handleShare = (id: number) => {
const article = results.find(n => n.id === id);
Alert.alert('分享', `分享文章: ${article?.title}`);
};
const handleArticlePress = (id: number) => {
Alert.alert('阅读', `阅读文章 ID: ${id}`);
};
交互功能包括收藏、分享和查看详情:
handleBookmark函数通过map方法更新指定文章的收藏状态handleShare函数通过Alert显示分享确认信息handleArticlePress函数通过Alert显示查看详情的确认信息
这些交互功能为用户提供了完整的操作体验,同时也为后续的功能扩展(如跳转到详情页、集成系统分享)做好了准备。
搜索结果
<View style={styles.searchCard}>
<TouchableOpacity onPress={() => onPress(result.id)}>
<Image source={{ uri: result.image }} style={styles.resultImage} />
</TouchableOpacity>
<View style={styles.resultContent}>
{/* 内容 */}
</View>
</View>
搜索结果卡片采用了左右布局结构,左侧是文章图片,右侧是详细信息。这种布局方式在新闻和资讯类应用中非常常见,能够清晰地展示信息,同时保持界面的整洁和有序。
响应式
const { width } = Dimensions.get('window');
通过 Dimensions.get('window') 获取屏幕宽度,为后续的响应式布局计算提供基础。虽然在当前实现中没有直接使用这个值进行动态计算,但这种模式为后续的布局调整(如适配不同屏幕尺寸)预留了扩展空间。
-
组件映射:
SafeAreaView→SafeArea或Flex容器ScrollView→List或Scroll组件TouchableOpacity→Button或Text+ 手势事件Image→Image组件View→Flex容器Text→Text组件TextInput→Input组件Alert→Dialog组件
-
图片加载适配:
- React Native 中使用
source={{ uri: result.image }}加载网络图片 - 鸿蒙系统中可以使用
Image组件的src属性,语法类似但可能需要调整
- React Native 中使用
这个搜索结果页面展示了 React Native 跨端开发的核心技术要点,通过合理的组件设计、清晰的状态管理、强大的搜索功能和细致的样式管理,实现了一个功能完整、用户体验良好的搜索结果页面。在鸿蒙系统适配方面,通过组件映射、样式适配和布局调整,可以快速实现跨端迁移,保持功能和视觉效果的一致性。
本次解析的代码是一套基于React Native原生API开发的资讯类应用搜索结果页核心实现,聚焦资讯类产品的搜索核心场景,打造了智能搜索栏+搜索历史/推荐双态展示+资讯卡片+底部导航的标准化移动端页面结构,同时整合了关键词搜索、历史快捷选择、收藏、分享、无结果兜底等资讯类应用高频交互能力。项目全程采用函数式组件+useState轻量状态管理,遵循组件化解耦与状态驱动视图核心思想,无任何第三方UI/业务库依赖,所有实现均基于React Native跨平台原生能力。
本项目的技术选型围绕跨端兼容性、原生体验、工程可维护性三大核心原则展开,所有选用的组件、API、语法均为React Native与鸿蒙平台的通用能力,无任何平台专属特性,为鸿蒙跨端落地奠定了极简的工程基础,同时贴合资讯类应用“轻量、高效、流畅”的产品特性,核心技术基底设计如下:
1. 原生组件
选用SafeAreaView、View、Text、TouchableOpacity、ScrollView、Image、TextInput等React Native核心原生组件,这类组件均已完成React Native for HarmonyOS的深度桥接,底层会被编译为对应平台的原生组件(鸿蒙Component、Android View、iOS UIView),基于原生渲染引擎执行,彻底规避WebView渲染的性能损耗。其中TextInput的输入交互、Image的远程URI加载、ScrollView的纵向滚动、TouchableOpacity的触摸反馈,在鸿蒙平台均能实现原生级体验;SafeAreaView会自动桥接鸿蒙的安全区域适配能力,兼容鸿蒙设备的刘海屏、折叠屏、底部导航栏,无需手动计算安全区域间距,多端布局适配一步到位。
2. 状态管理
采用React Hooks的useState实现全页面的状态管理,包括资讯原始数据、搜索关键词、搜索历史三大核心状态,严格遵循React状态不可变与单向数据流原则。这种轻量状态管理方式与鸿蒙ArkUI的@State/@Prop状态管理理念高度同源——均通过状态变化驱动视图重渲染,无复杂的状态流转逻辑。在鸿蒙跨端开发中,无需重构状态管理代码,即可保证多端的状态与视图一致性,大幅降低跨端开发的学习与迁移成本,同时轻量的状态设计让资讯类应用的页面渲染更高效,适配鸿蒙设备的性能要求。
本页面的核心设计亮点是基于搜索关键词的双态页面展示——无搜索关键词时展示「搜索历史+推荐内容」,有搜索关键词时展示「精准搜索结果」,两种状态的切换完全由searchQuery状态驱动,同时整合了关键词模糊搜索、搜索历史快捷选择、无结果兜底等资讯类搜索核心能力,所有逻辑均为通用JavaScript代码,在鸿蒙平台的JS引擎中可直接执行,无跨端差异,核心实现要点如下:
1. 核心状态初始化
通过三个独立的useState钩子初始化核心状态,实现资讯数据、搜索关键词、搜索历史的解耦管理,每个状态对应独立的业务维度,拥有专属的状态更新方法,便于后续拓展单一维度的逻辑,核心代码如下:
// 资讯原始数据,直接复用模拟数据,内置收藏等交互状态
const [results, setResults] = useState(SEARCH_RESULTS);
// 搜索关键词,控制页面双态切换的核心状态
const [searchQuery, setSearchQuery] = useState('');
// 搜索历史,存储用户过往搜索关键词,限制最大条数
const [searchHistory, setSearchHistory] = useState(['科技', '教育', '健康']);
独立的状态设计让视图与状态的绑定更清晰,在鸿蒙平台重渲染时,仅会更新关联的视图区域,避免全量重渲染,提升鸿蒙设备的渲染性能,同时符合资讯类应用“快速响应”的产品需求。
2. 双态页面切换
通过三元表达式判断searchQuery是否为空,实现「搜索历史+推荐内容」与「精准搜索结果」的页面双态切换,核心渲染逻辑如下:
{searchQuery ? (
// 有搜索关键词:展示搜索结果模块
<>...</>
) : (
// 无搜索关键词:展示搜索历史+推荐内容模块
<>...</>
)}
这种实现方式完全基于React的状态驱动视图思想,无任何手动DOM操作,所有视图切换均由searchQuery状态变化触发。在鸿蒙平台中,三元表达式为通用JavaScript语法,视图切换的底层由React Native与鸿蒙的桥接层处理,转换为鸿蒙ArkUI的条件渲染逻辑,保证多端的切换体验一致。
3. 关键词模糊搜索
定义handleSearch方法实现关键词模糊搜索,贴合资讯类应用用户的搜索习惯,支持对资讯的标题、摘要、分类三个维度进行关键词匹配,核心逻辑如下:
const filtered = SEARCH_RESULTS.filter(item =>
item.title.toLowerCase().includes(query.toLowerCase()) ||
item.summary.toLowerCase().includes(query.toLowerCase()) ||
item.category.toLowerCase().includes(query.toLowerCase())
);
setResults(filtered);
通过toLowerCase()实现大小写不敏感搜索,提升用户搜索体验;采用Array.prototype.filter通用数组方法实现筛选,无平台专属API,在鸿蒙、Android、iOS的JS引擎中均能正常执行。同时方法中预留了真实API调用的注释,后续对接后端搜索接口时,仅需替换筛选逻辑,无需修改其他业务代码,工程可维护性强。
4. 搜索历史管理
在handleSearch方法中整合搜索历史管理逻辑,实现关键词去重与最大长度限制(最多保存5条),贴合资讯类应用的实际产品需求,核心逻辑如下:
if (!searchHistory.includes(query)) {
setSearchHistory(prev => [query, ...prev.slice(0, 4)]);
}
通过!searchHistory.includes(query)实现关键词去重,避免历史记录重复;通过扩展运算符...将新关键词添加到历史头部,再通过slice(0,4)截取前4条原有历史,保证搜索历史最多保存5条。所有操作均严格遵循状态不可变原则,通过复制原有状态并修改的方式更新,避免直接操作原数组导致的状态异常,这种实现方式与鸿蒙ArkUI的状态更新规范一致,跨端无兼容问题。
5. 搜索历史快捷选择
为搜索历史项绑定点击事件,实现一键填充关键词+触发搜索的快捷操作,核心逻辑如下:
const selectFromHistory = (query: string) => {
setSearchQuery(query);
handleSearch(query);
};
用户点击历史关键词时,先将关键词填充到搜索输入框(更新searchQuery状态),再自动触发搜索方法,无需用户手动输入与提交,大幅提升资讯类应用的搜索操作效率。该逻辑为通用JavaScript方法,在鸿蒙平台中,TouchableOpacity的点击事件会桥接为鸿蒙的原生触摸事件,方法调用无跨端差异。
6. 无结果兜底
在搜索结果模块中添加无结果兜底逻辑,当筛选后的结果长度为0时,展示友好的无结果提示,核心渲染逻辑如下:
{results.length > 0 ? (
results.map(result => <SearchCard key={result.id} {...props} />)
) : (
<View style={styles.noResultContainer}>
<Text style={styles.noResultText}>未找到相关结果</Text>
<Text style={styles.noResultSubtext}>尝试使用其他关键词搜索</Text>
</View>
)}
无结果兜底是资讯类应用的必备能力,该实现方式通过判断数组长度实现,无平台专属特性,在鸿蒙平台的渲染效果与其他端一致,同时友好的提示文案能提升用户的搜索体验,避免无反馈的尴尬场景。
7. 搜索输入交互
为搜索输入框TextInput整合回车提交搜索与清空按钮两大高频交互能力,贴合移动端用户的输入习惯:
- 回车提交:通过
onSubmitEditing事件实现,用户在输入框中按下回车时自动触发handleSearch方法,无需点击额外的搜索按钮; - 清空按钮:通过条件渲染实现,当
searchQuery不为空时展示清空按钮,点击后调用clearSearch方法,重置searchQuery为空并恢复原始资讯数据,实现一键清空搜索。
TextInput的所有事件与属性均为React Native原生能力,且已完成鸿蒙桥接,在鸿蒙平台中,回车事件会桥接为鸿蒙的原生键盘回车事件,清空按钮的触摸反馈为鸿蒙原生效果,多端交互体验高度一致。
真实演示案例代码:
// app.tsx
import React, { useState } from 'react';
import { SafeAreaView, View, Text, StyleSheet, TouchableOpacity, ScrollView, Image, Dimensions, Alert, TextInput } from 'react-native';
// 图标库
const ICONS = {
home: '🏠',
search: '🔍',
user: '👤',
news: '📰',
bookmark: '🔖',
share: '📤',
time: '🕒',
close: '❌',
};
const { width } = Dimensions.get('window');
// 模拟搜索结果数据
const SEARCH_RESULTS = [
{
id: 1,
title: '科技发展新趋势:人工智能引领未来',
summary: '人工智能技术正在快速发展,为各行各业带来前所未有的变化和机遇。',
author: '张记者',
time: '2小时前',
category: '科技',
readTime: '5分钟',
image: 'https://picsum.photos/300/200?random=1',
comments: 24,
isBookmarked: false,
},
{
id: 2,
title: '环保政策新动向:绿色能源成焦点',
summary: '政府发布新的环保政策,推动绿色能源产业发展,助力碳中和目标。',
author: '李编辑',
time: '4小时前',
category: '环保',
readTime: '3分钟',
image: 'https://picsum.photos/300/200?random=2',
comments: 18,
isBookmarked: true,
},
{
id: 3,
title: '教育改革新举措:素质教育全面推行',
summary: '教育部宣布全面推行素质教育,注重学生全面发展和创新能力培养。',
author: '王老师',
time: '6小时前',
category: '教育',
readTime: '4分钟',
image: 'https://picsum.photos/300/200?random=3',
comments: 32,
isBookmarked: false,
},
{
id: 4,
title: '健康生活:运动与营养的重要性',
summary: '专家强调运动与均衡营养对健康的重要性,提出科学生活方式建议。',
author: '陈医生',
time: '8小时前',
category: '健康',
readTime: '6分钟',
image: 'https://picsum.photos/300/200?random=4',
comments: 15,
isBookmarked: false,
},
{
id: 5,
title: '经济发展:新兴产业蓬勃发展',
summary: '新兴产业如新能源汽车、生物医药等领域呈现强劲增长态势。',
author: '刘分析师',
time: '10小时前',
category: '经济',
readTime: '7分钟',
image: 'https://picsum.photos/300/200?random=5',
comments: 27,
isBookmarked: true,
},
{
id: 6,
title: '文化传承:传统艺术焕发新生',
summary: '传统文化与现代技术结合,让传统艺术形式焕发新的生命力。',
author: '赵学者',
time: '12小时前',
category: '文化',
readTime: '4分钟',
image: 'https://picsum.photos/300/200?random=6',
comments: 9,
isBookmarked: false,
},
{
id: 7,
title: '国际关系:全球合作应对挑战',
summary: '各国加强合作,共同应对气候变化、疫情等全球性挑战。',
author: '外交专家',
time: '14小时前',
category: '国际',
readTime: '5分钟',
image: 'https://picsum.photos/300/200?random=7',
comments: 16,
isBookmarked: false,
},
{
id: 8,
title: '科技创新:量子计算新突破',
summary: '科学家在量子计算领域取得重大进展,为未来计算技术奠定基础。',
author: '科技日报',
time: '16小时前',
category: '科技',
readTime: '6分钟',
image: 'https://picsum.photos/300/200?random=8',
comments: 31,
isBookmarked: true,
},
];
const SearchCard: React.FC<{
result: any,
onBookmark: (id: number) => void,
onShare: (id: number) => void,
onPress: (id: number) => void
}> = ({ result, onBookmark, onShare, onPress }) => {
return (
<View style={styles.searchCard}>
<TouchableOpacity onPress={() => onPress(result.id)}>
<Image source={{ uri: result.image }} style={styles.resultImage} />
</TouchableOpacity>
<View style={styles.resultContent}>
<View style={styles.resultHeader}>
<Text style={styles.category}>{result.category}</Text>
<View style={styles.timeRow}>
<Text style={styles.timeIcon}>{ICONS.time}</Text>
<Text style={styles.readTime}>{result.readTime}</Text>
</View>
</View>
<TouchableOpacity onPress={() => onPress(result.id)}>
<Text style={styles.title}>{result.title}</Text>
<Text style={styles.summary}>{result.summary}</Text>
</TouchableOpacity>
<View style={styles.resultFooter}>
<View style={styles.authorInfo}>
<Text style={styles.author}>{ICONS.user} {result.author}</Text>
<Text style={styles.postTime}>{result.time}</Text>
</View>
<View style={styles.actions}>
<TouchableOpacity style={styles.actionButton} onPress={() => onBookmark(result.id)}>
<Text style={styles.actionIcon}>{result.isBookmarked ? '★' : ICONS.bookmark}</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.actionButton} onPress={() => onShare(result.id)}>
<Text style={styles.actionIcon}>{ICONS.share}</Text>
</TouchableOpacity>
<View style={styles.commentRow}>
<Text style={styles.commentIcon}>💬</Text>
<Text style={styles.commentCount}>{result.comments}</Text>
</View>
</View>
</View>
</View>
</View>
);
};
const SearchResultPage: React.FC = () => {
const [results, setResults] = useState(SEARCH_RESULTS);
const [searchQuery, setSearchQuery] = useState('');
const [searchHistory, setSearchHistory] = useState(['科技', '教育', '健康']);
const handleSearch = (query: string) => {
if (query.trim() !== '') {
// 在实际应用中,这里应该调用API进行搜索
// 暂时过滤现有数据作为演示
const filtered = SEARCH_RESULTS.filter(item =>
item.title.toLowerCase().includes(query.toLowerCase()) ||
item.summary.toLowerCase().includes(query.toLowerCase()) ||
item.category.toLowerCase().includes(query.toLowerCase())
);
setResults(filtered);
// 添加到搜索历史
if (!searchHistory.includes(query)) {
setSearchHistory(prev => [query, ...prev.slice(0, 4)]);
}
} else {
setResults(SEARCH_RESULTS);
}
};
const handleBookmark = (id: number) => {
setResults(results.map(item =>
item.id === id ? { ...item, isBookmarked: !item.isBookmarked } : item
));
};
const handleShare = (id: number) => {
const article = results.find(n => n.id === id);
Alert.alert('分享', `分享文章: ${article?.title}`);
};
const handleArticlePress = (id: number) => {
Alert.alert('阅读', `阅读文章 ID: ${id}`);
};
const clearSearch = () => {
setSearchQuery('');
setResults(SEARCH_RESULTS);
};
const selectFromHistory = (query: string) => {
setSearchQuery(query);
handleSearch(query);
};
return (
<SafeAreaView style={styles.container}>
{/* 头部搜索栏 */}
<View style={styles.header}>
<View style={styles.searchContainer}>
<Text style={styles.searchIcon}>{ICONS.search}</Text>
<TextInput
style={styles.searchInput}
placeholder="搜索新闻、文章或话题..."
value={searchQuery}
onChangeText={setSearchQuery}
onSubmitEditing={() => handleSearch(searchQuery)}
/>
{searchQuery ? (
<TouchableOpacity style={styles.clearButton} onPress={clearSearch}>
<Text style={styles.clearIcon}>{ICONS.close}</Text>
</TouchableOpacity>
) : null}
</View>
</View>
{/* 搜索结果 */}
{searchQuery ? (
<>
<Text style={styles.sectionTitle}>搜索结果</Text>
<Text style={styles.sectionSubtitle}>找到 {results.length} 条相关结果</Text>
<ScrollView style={styles.content}>
{results.length > 0 ? (
results.map(result => (
<SearchCard
key={result.id}
result={result}
onBookmark={handleBookmark}
onShare={handleShare}
onPress={handleArticlePress}
/>
))
) : (
<View style={styles.noResultContainer}>
<Text style={styles.noResultText}>未找到相关结果</Text>
<Text style={styles.noResultSubtext}>尝试使用其他关键词搜索</Text>
</View>
)}
</ScrollView>
</>
) : (
<>
<Text style={styles.sectionTitle}>热门搜索</Text>
<Text style={styles.sectionSubtitle}>大家都在搜什么</Text>
<ScrollView style={styles.content}>
<View style={styles.historyContainer}>
{searchHistory.map((item, index) => (
<TouchableOpacity
key={index}
style={styles.historyItem}
onPress={() => selectFromHistory(item)}
>
<Text style={styles.historyText}>{item}</Text>
</TouchableOpacity>
))}
</View>
<Text style={styles.recommendTitle}>推荐内容</Text>
{SEARCH_RESULTS.slice(0, 4).map(result => (
<SearchCard
key={result.id}
result={result}
onBookmark={handleBookmark}
onShare={handleShare}
onPress={handleArticlePress}
/>
))}
</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.news}</Text>
<Text style={styles.navText}>资讯</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.navItem}>
<Text style={styles.navIcon}>{ICONS.bookmark}</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: {
padding: 16,
backgroundColor: '#ffffff',
borderBottomWidth: 1,
borderBottomColor: '#e2e8f0',
},
searchContainer: {
flexDirection: 'row',
alignItems: 'center',
backgroundColor: '#f1f5f9',
borderRadius: 20,
paddingHorizontal: 12,
},
searchIcon: {
fontSize: 18,
color: '#64748b',
marginRight: 8,
},
searchInput: {
flex: 1,
paddingVertical: 12,
fontSize: 16,
color: '#1e293b',
},
clearButton: {
padding: 4,
},
clearIcon: {
fontSize: 18,
color: '#94a3b8',
},
content: {
flex: 1,
padding: 16,
},
sectionTitle: {
fontSize: 22,
fontWeight: 'bold',
color: '#1e293b',
marginBottom: 4,
marginLeft: 16,
},
sectionSubtitle: {
fontSize: 14,
color: '#64748b',
marginBottom: 16,
marginLeft: 16,
},
searchCard: {
backgroundColor: '#ffffff',
borderRadius: 12,
marginBottom: 16,
overflow: 'hidden',
elevation: 3,
shadowColor: '#000',
shadowOffset: { width: 0, height: 2 },
shadowOpacity: 0.1,
shadowRadius: 4,
},
resultImage: {
width: '100%',
height: 160,
},
resultContent: {
padding: 16,
},
resultHeader: {
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
marginBottom: 8,
},
category: {
fontSize: 12,
color: '#ffffff',
backgroundColor: '#3b82f6',
paddingHorizontal: 8,
paddingVertical: 4,
borderRadius: 12,
},
timeRow: {
flexDirection: 'row',
alignItems: 'center',
},
timeIcon: {
fontSize: 12,
color: '#94a3b8',
marginRight: 4,
},
readTime: {
fontSize: 12,
color: '#94a3b8',
},
title: {
fontSize: 16,
fontWeight: 'bold',
color: '#1e293b',
marginBottom: 8,
lineHeight: 22,
},
summary: {
fontSize: 14,
color: '#64748b',
lineHeight: 18,
marginBottom: 12,
},
resultFooter: {
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
},
authorInfo: {
flex: 1,
},
author: {
fontSize: 12,
color: '#94a3b8',
marginBottom: 4,
},
postTime: {
fontSize: 12,
color: '#94a3b8',
},
actions: {
flexDirection: 'row',
alignItems: 'center',
},
actionButton: {
marginLeft: 12,
},
actionIcon: {
fontSize: 16,
color: '#94a3b8',
},
commentRow: {
flexDirection: 'row',
alignItems: 'center',
marginLeft: 12,
},
commentIcon: {
fontSize: 14,
color: '#94a3b8',
marginRight: 4,
},
commentCount: {
fontSize: 12,
color: '#94a3b8',
},
historyContainer: {
flexDirection: 'row',
flexWrap: 'wrap',
marginBottom: 24,
},
historyItem: {
backgroundColor: '#e2e8f0',
paddingHorizontal: 12,
paddingVertical: 6,
borderRadius: 16,
marginRight: 8,
marginBottom: 8,
},
historyText: {
fontSize: 14,
color: '#475569',
},
recommendTitle: {
fontSize: 18,
fontWeight: 'bold',
color: '#1e293b',
marginBottom: 16,
},
noResultContainer: {
alignItems: 'center',
justifyContent: 'center',
paddingVertical: 40,
},
noResultText: {
fontSize: 18,
color: '#64748b',
marginBottom: 8,
},
noResultSubtext: {
fontSize: 14,
color: '#94a3b8',
},
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 SearchResultPage;

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

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

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

本文介绍了一个基于React Native的资讯类应用搜索结果页面实现方案。采用函数式组件和useState轻量状态管理,通过原生组件构建了包含智能搜索栏、搜索历史、资讯卡片和底部导航的标准页面结构。核心功能包括关键词搜索、历史记录管理、收藏/分享交互等,全部基于跨平台原生能力实现,无第三方依赖。特别设计了搜索关键词的双态展示逻辑,支持搜索结果与推荐内容的智能切换。该方案遵循组件化解耦原则,采用原生渲染引擎保障性能,并针对鸿蒙平台适配进行了组件映射设计,确保跨端兼容性。
欢迎大家加入开源鸿蒙跨平台开发者社区,一起共建开源鸿蒙跨平台生态。
更多推荐


所有评论(0)