news 2026/1/13 7:29:42

React Native鸿蒙跨平台开发AsyncStorage是提供的一个简单的、异步的、持久化的、key-value存储系统,非常适合存储小的数据片段,如用户的登录令牌、偏好设置等

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
React Native鸿蒙跨平台开发AsyncStorage是提供的一个简单的、异步的、持久化的、key-value存储系统,非常适合存储小的数据片段,如用户的登录令牌、偏好设置等

在React Native中,实现本地数据存储有多种方式,每种方式有其特定的使用场景和优缺点。以下是几种常见的本地数据存储方式:

  1. AsyncStorage

AsyncStorage是React Native提供的一个简单的、异步的、持久化的、key-value存储系统。它非常适合存储小的数据片段,例如用户的登录令牌、偏好设置等。

使用示例:

importAsyncStoragefrom'@react-native-async-storage/async-storage';// 存储数据AsyncStorage.setItem('key','value').then(()=>{console.log('Data saved');}).catch(error=>{console.error('Error saving data',error);});// 读取数据AsyncStorage.getItem('key').then(value=>{console.log('Data retrieved:',value);}).catch(error=>{console.error('Error retrieving data',error);});
  1. SQLite 数据库

对于需要存储大量结构化数据的应用,可以使用SQLite数据库。React Native提供了react-native-sqlite-storage这样的库来操作SQLite数据库。

安装库:

npminstall--save react-native-sqlite-storage

使用示例:

importSQLitefrom'react-native-sqlite-storage';SQLite.DEBUG(true);// 启用调试模式(可选)vardb=SQLite.openDatabase({name:'mydb.db',location:'default'},()=>{console.log('Database opened');},(error)=>{console.error('Error opening database:',error);});db.transaction(tx=>{tx.executeSql('CREATE TABLE IF NOT EXISTS MyTable (id INTEGER PRIMARY KEY, data TEXT)');tx.executeSql('INSERT INTO MyTable (data) VALUES (?)',['test']);});
  1. Realm Database

Realm是一个移动数据库,它提供了一个面向对象的编程接口,使得操作数据库更加简单和直观。它支持Harmony、Harmony和React Native。

安装库:

npminstallrealm @realm/react --save

使用示例:

importRealmfrom'realm';import{useRealm}from'@realm/react';// 用于React hooks的集成constMySchema={name:'MyObject',properties:{id:'int',data:'string'},primaryKey:'id'};constrealm=newRealm({schema:[MySchema]});// 初始化Realm实例,并定义schemaconstrealmInstance=useRealm(realm);// 在React组件中使用Realm实例(如果你使用hooks)
  1. Redux Persist 或其他状态管理库结合 LocalStorage 或 AsyncStorage

如果你的应用使用了Redux进行状态管理,可以使用redux-persist库结合AsyncStorageLocalStorage来持久化Redux的状态。这样,应用的状态就可以在应用重启后恢复。

安装库:

npminstallredux-persist @react-native-async-storage/async-storage --save // 注意:@react-native-async-storage/async-storage 是 AsyncStorage 的替代品,用于React Native0.60及以上版本。如果你使用的是旧版本,请使用 @react-native-community/async-storage。

配置示例:

import{persistStore,persistReducer}from'redux-persist';importstoragefrom'@react-native-async-storage/async-storage';// 或者使用 @react-native-community/async-storage 对于旧版本React Native。import{createStore}from'redux';importrootReducerfrom'./reducers';// 你的reducer文件路径。constpersistConfig={key:'root',// 存储的key值。可以根据需要更改。storage,// 使用AsyncStorage作为存储介质。也可以使用其他支持的存储方式。例如:localStorage。对于React Native,推荐使用AsyncStorage。 如果你使用的是旧版本React Native,请使用AsyncStorage的社区版本。 例如:import AsyncStorage from '@react-native-community/async-storage'; 并且将storage设置为 AsyncStorage。 而不是'@react-native-async-storage/async-storage'。 这是因为'@react-native-async-storage/async-storage'是为React Native

真实案例演示代码:

// app.tsximportReact,{useState}from'react';import{View,Text,StyleSheet,TouchableOpacity,TextInput,ScrollView,Alert,Image}from'react-native';constApp=()=>{const[key,setKey]=useState('');const[value,setValue]=useState('');const[items,setItems]=useState<Record<string,string>>({});const[editMode,setEditMode]=useState(false);// Base64 iconsconsticons={save:'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9IiM0Mjg1RjQiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIj48cGF0aCBkPSJNMTkgMjFINGEyIDIgMCAwIDEtMi0yVjVhMiAyIDAgMCAxIDItMmg3Ij48L3BhdGg+PHBvbHlsaW5lIHBvaW50cz0iMTcgMiA5LjUgMiA3IDcgMTcgNyAxNyAyIj48L3BvbHlsaW5lPjxsaW5lIHgxPSI5IiB5MT0iOSIgeDI9IjE1IiB5Mj0iOSI+PC9saW5lPjxsaW5lIHgxPSI5IiB5MT0iMTMiIHgyPSIxNSIgeTI9IjEzIj48L2xpbmU+PGxpbmUgeDE9IjkiIHkxPSIxNyIgeDI9IjE1IiB5Mj0iMTciPjwvbGluZT48L3N2Zz4=',delete:'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9IiNFRTQ0M0EiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIj48cGF0aCBkPSJNMTkgNlY1YTIgMiAwIDAgMC0yLTJIN2EyIDIgMCAwIDAtMiAydjEiPjwvcGF0aD48bGluZSB4MT0iOCIgeTE9IjkiIHgyPSIxNiIgeTI9IjkiPjwvbGluZT48cGF0aCBkPSJNMTkgNlYyMGEyIDIgMCAwIDEtMiAyaC04YTIgMiAwIDAgMS0yLTJWNiI+PC9wYXRoPjxyZWN0IHg9IjkiIHk9IjYiIHdpZHRoPSIxMiIgaGVpZ2h0PSIxOCIgcng9IjIiIHJ5PSIyIj48L3JlY3Q+PC9zdmc+',edit:'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9IiM0Mjg1RjQiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIj48cGF0aCBkPSJNMTcgM0EyIDIgMCAwIDAgMTUuNTg2IDMuNDY0TDMuNTg2IDE1LjQ2NEEyIDIgMCAwIDAgMyAyMWgyLjVhMSAxIDAgMCAwIC43MDctLjI5M2wxMi0xMkExIDIgMCAwIDAgMTcgM3oiPjwvcGF0aD48L3N2Zz4=',clear:'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9IiM5OTkiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIj48cGF0aCBkPSJNMTggNiA2IDE4Ij48L3BhdGg+PHBhdGggZD0iTTE4IDE4IDYgNiI+PC9wYXRoPjwvc3ZnPg=='};constsaveData=()=>{if(!key.trim()||!value.trim()){Alert.alert('错误','键和值都不能为空');return;}setItems(prev=>({...prev,[key]:value}));setKey('');setValue('');Alert.alert('成功','数据已保存');};constdeleteItem=(itemKey:string)=>{setItems(prev=>{constnewItems={...prev};deletenewItems[itemKey];returnnewItems;});Alert.alert('成功','数据已删除');};constclearAll=()=>{setItems({});Alert.alert('成功','所有数据已清空');};constloadItem=(itemKey:string,itemValue:string)=>{if(editMode){setKey(itemKey);setValue(itemValue);}};return(<ScrollView style={styles.container}><View style={styles.header}><Text style={styles.title}>本地数据存储</Text><Text style={styles.subtitle}>简易键值对存储系统</Text></View><View style={styles.formContainer}><View style={styles.inputGroup}><Text style={styles.label}>(Key)</Text><TextInput style={styles.input}value={key}onChangeText={setKey}placeholder="输入键名"/></View><View style={styles.inputGroup}><Text style={styles.label}>(Value)</Text><TextInput style={[styles.input,styles.textArea]}value={value}onChangeText={setValue}placeholder="输入值"multiline numberOfLines={3}/></View><View style={styles.buttonRow}><TouchableOpacity style={[styles.button,styles.saveButton]}onPress={saveData}><Image source={{uri:icons.save}}style={styles.buttonIcon}/><Text style={styles.buttonText}>保存</Text></TouchableOpacity><TouchableOpacity style={[styles.button,styles.editButton]}onPress={()=>setEditMode(!editMode)}><Image source={{uri:icons.edit}}style={styles.buttonIcon}/><Text style={styles.buttonText}>{editMode?'取消编辑':'编辑模式'}</Text></TouchableOpacity></View></View><View style={styles.dataContainer}><View style={styles.dataHeader}><Text style={styles.dataTitle}>已存储的数据</Text>{Object.keys(items).length>0&&(<TouchableOpacity style={styles.clearButton}onPress={clearAll}><Image source={{uri:icons.clear}}style={styles.clearIcon}/><Text style={styles.clearText}>清空</Text></TouchableOpacity>)}</View>{Object.keys(items).length===0?(<View style={styles.emptyContainer}><Text style={styles.emptyText}>暂无数据</Text></View>):(<View style={styles.dataList}>{Object.entries(items).map(([itemKey,itemValue])=>(<View key={itemKey}style={styles.dataItem}><TouchableOpacity style={styles.dataContent}onPress={()=>loadItem(itemKey,itemValue)}><Text style={styles.itemKey}>{itemKey}</Text><Text style={styles.itemValue}numberOfLines={2}>{itemValue}</Text></TouchableOpacity><TouchableOpacity style={styles.deleteButton}onPress={()=>deleteItem(itemKey)}><Image source={{uri:icons.delete}}style={styles.deleteIcon}/></TouchableOpacity></View>))}</View>)}</View></ScrollView>);};conststyles=StyleSheet.create({container:{flex:1,backgroundColor:'#f5f8fa',padding:20},header:{alignItems:'center',marginBottom:30,paddingTop:20},title:{fontSize:26,fontWeight:'bold',color:'#2c3e50'},subtitle:{fontSize:14,color:'#7f8c8d',marginTop:5},formContainer:{backgroundColor:'#fff',borderRadius:16,padding:20,marginBottom:20,elevation:3,shadowColor:'#000',shadowOffset:{width:0,height:2},shadowOpacity:0.1,shadowRadius:4},inputGroup:{marginBottom:20},label:{fontSize:16,fontWeight:'600',color:'#34495e',marginBottom:8},input:{borderWidth:1,borderColor:'#ddd',borderRadius:12,padding:14,fontSize:16,backgroundColor:'#fafafa'},textArea:{height:80,textAlignVertical:'top'},buttonRow:{flexDirection:'row',justifyContent:'space-between'},button:{flexDirection:'row',alignItems:'center',justifyContent:'center',paddingVertical:14,paddingHorizontal:20,borderRadius:12,flex:1,marginHorizontal:5},saveButton:{backgroundColor:'#4285F4'},editButton:{backgroundColor:'#34A853'},buttonIcon:{width:20,height:20,marginRight:8},buttonText:{color:'#fff',fontSize:16,fontWeight:'600'},dataContainer:{backgroundColor:'#fff',borderRadius:16,padding:20,elevation:3,shadowColor:'#000',shadowOffset:{width:0,height:2},shadowOpacity:0.1,shadowRadius:4},dataHeader:{flexDirection:'row',justifyContent:'space-between',alignItems:'center',marginBottom:15},dataTitle:{fontSize:20,fontWeight:'bold',color:'#2c3e50'},clearButton:{flexDirection:'row',alignItems:'center'},clearIcon:{width:18,height:18,marginRight:5},clearText:{color:'#999',fontSize:14},emptyContainer:{paddingVertical:40,alignItems:'center'},emptyText:{color:'#999',fontSize:16},dataList:{marginTop:10},dataItem:{flexDirection:'row',alignItems:'center',paddingVertical:15,borderBottomWidth:1,borderBottomColor:'#eee'},dataContent:{flex:1,paddingRight:10},itemKey:{fontSize:16,fontWeight:'600',color:'#34495e',marginBottom:5},itemValue:{fontSize:14,color:'#7f8c8d',lineHeight:20},deleteButton:{padding:10},deleteIcon:{width:22,height:22}});exportdefaultApp;

这段React Native代码实现了一个本地数据存储管理系统的用户界面和交互逻辑,其核心原理基于React的状态管理和React Native的原生组件系统。从鸿蒙系统适配的角度深入分析,该代码体现了现代跨平台移动应用开发的核心理念。

代码通过useState钩子管理三个核心状态:key(键名)、value(值)和items(存储的键值对集合)。这种状态管理模式与鸿蒙系统的分布式数据管理理念高度契合,鸿蒙系统强调数据驱动的UI更新机制,而React的单向数据流正好满足这一需求。当用户在输入框中输入数据时,通过onChangeText回调函数实时更新组件状态,触发界面重新渲染,这种响应式更新机制在鸿蒙设备上能够提供流畅的用户体验。

saveData函数实现了数据的存储逻辑,通过展开运算符创建新的items对象,避免直接修改原状态,这符合React不可变数据的原则。在鸿蒙系统中,这种数据处理方式能够更好地适配其分布式数据管理机制,确保数据状态的一致性和可预测性。函数中包含的数据验证逻辑体现了良好的用户体验设计,通过Alert组件提供即时反馈,这种交互模式在鸿蒙系统的原生应用中也广泛使用。

deleteItem函数采用delete操作符从items对象中移除指定键值对,通过创建新对象的方式保持状态的不可变性。这种实现方式在鸿蒙系统的内存管理中具有优势,能够有效避免内存泄漏问题。clearAll函数通过设置空对象实现数据清空,体现了简洁高效的设计思想。

loadItem函数实现了编辑模式下的数据加载功能,当用户点击已存储的数据项时,将选中项的键值填充到输入框中。这种交互模式在鸿蒙系统的应用设计中很常见,体现了直观易用的用户界面设计理念。

UI布局采用ScrollView作为根容器,确保内容在小屏幕设备上的可滚动性,这在鸿蒙系统的多设备适配中至关重要。View组件作为布局容器,通过flex布局实现响应式设计,能够自适应不同尺寸的鸿蒙设备屏幕。

TextInput组件实现了用户输入功能,通过multiline属性支持多行文本输入,numberOfLines属性控制显示行数。在鸿蒙系统中,这种输入组件会自动适配系统的输入法和键盘布局,提供原生的输入体验。TouchableOpacity组件实现触摸交互,其内置的触摸反馈效果符合鸿蒙系统的交互设计规范。

样式系统采用StyleSheet.create方式定义,这种做法在鸿蒙环境中能够获得更好的性能表现。通过样式对象的组合应用,实现复杂的视觉效果。背景色#f5f8fa等设计细节体现了现代化的UI设计理念,与鸿蒙系统的设计语言保持一致。

数据展示区域通过Object.entries方法将键值对转换为数组进行遍历渲染,每个数据项包含内容展示区和删除按钮。这种列表渲染模式在鸿蒙应用中广泛使用,能够高效处理动态数据集合。

整体而言,该代码通过React Native的跨平台能力,充分利用了鸿蒙系统的原生特性,在保持代码一致性的同时,为用户提供接近原生应用的使用体验。代码结构清晰,状态管理合理,交互逻辑完善,体现了现代移动应用开发的最佳实践。


打包

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

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

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

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

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/1/12 15:44:43

pyside6.QtCore.Slot 的简单研究

在 PySide6 中&#xff0c;Slot() 是 信号与槽&#xff08;Signal & Slot&#xff09;机制 的核心装饰器&#xff0c;用于将普通 Python 方法声明为 槽函数&#xff08;Slot&#xff09;—— 槽函数是专门响应信号&#xff08;Signal&#xff09;触发的回调方法&#xff0c…

作者头像 李华
网站建设 2026/1/13 5:21:08

在DevSecOps中,如何将安全测试(SAST/DAST等) 无缝集成到CI/CD流水线?

一、核心理念:安全左移,持续防护 将安全测试从传统“发布前检测”转变为开发全流程的嵌入式检查,实现“安全即代码”。 二、集成架构设计 分层安全测试策略 text CI/CD流水线安全防护链: ├── 提交前(Pre-commit) │ ├── Git Hooks:代码规范/敏感信息扫描 │…

作者头像 李华
网站建设 2026/1/12 16:49:59

腾讯云云渠道商:如何利用镜像实现跨云平台迁移?

一、引言 随着多云战略的普及&#xff0c;跨云迁移已成为企业数字化转型的关键环节。数据显示&#xff0c;超过40%​ 的企业采用多云架构&#xff0c;每年平均迁移23个应用。传统迁移方式存在停机时间长&#xff08;平均8-12小时&#xff09;、数据丢失风险&#xff08;高达15%…

作者头像 李华
网站建设 2026/1/12 18:55:54

ThinkPad风扇控制终极指南:让你的笔记本告别噪音烦恼

ThinkPad风扇控制终极指南&#xff1a;让你的笔记本告别噪音烦恼 【免费下载链接】TPFanCtrl2 ThinkPad Fan Control 2 (Dual Fan) for Windows 10 and 11 项目地址: https://gitcode.com/gh_mirrors/tp/TPFanCtrl2 还在忍受ThinkPad风扇的嗡嗡声吗&#xff1f;无论是编…

作者头像 李华
网站建设 2026/1/13 7:25:33

量化模型部署:LobeChat运行7B级别模型的可行性

量化模型部署&#xff1a;LobeChat运行7B级别模型的可行性 在个人开发者和小型团队中&#xff0c;越来越多的人希望搭建属于自己的AI对话系统——不依赖OpenAI、无需支付高昂API费用&#xff0c;还能保障数据隐私。然而&#xff0c;现实挑战摆在眼前&#xff1a;像LLaMA-2-7B或…

作者头像 李华