在React Native鸿蒙跨平台开发组件(Hong Components,这里指的是一个虚构或特定的组件名称,假定其为一种自定义或第三方组件)并实现保养日志记录功能
本文介绍了在React Native中开发鸿组件并实现保养日志记录功能的方法。通过初始化项目、安装日志库(react-native-logs)、创建鸿组件并集成日志功能,展示了完整的实现流程。文中提供了详细的代码示例,包括组件创建、日志记录和按钮交互逻辑。还介绍了如何查看日志输出,并提到可通过react-native-logs库进行高级配置,如自定义日志级别和存储位置。最后给出一个实际项目案例,演
在React Native中开发鸿蒙组件(Hong Components,这里指的是一个虚构或特定的组件名称,假定其为一种自定义或第三方组件)并实现保养日志记录功能,可以通过多种方式来实现。这里我将介绍一种常见的方法,使用React Native的内置功能结合第三方库来完成。
步骤 1: 初始化React Native项目
如果你还没有创建React Native项目,可以使用以下命令来创建一个:
npx react-native init MyProject
cd MyProject
步骤 2: 安装必要的库
为了记录日志,你可以使用如react-native-logs这样的库。首先,安装这个库:
npm install react-native-logs
或者使用yarn:
yarn add react-native-logs
步骤 3: 配置鸿组件
假定你已经有了一个鸿组件的代码。如果没有,你可以创建一个简单的组件作为示例:
// HongComponent.js
import React from 'react';
import { View, Text, Button } from 'react-native';
import Logs from 'react-native-logs';
class HongComponent extends React.Component {
logMaintenance = () => {
const message = '执行了保养操作';
Logs.info(message); // 使用Logs库记录信息日志
console.log(message); // 同时使用console.log记录日志到控制台
};
render() {
return (
<View>
<Text>鸿组件</Text>
<Button title="执行保养" onPress={this.logMaintenance} />
</View>
);
}
}
export default HongComponent;
步骤 4: 使用鸿组件并查看日志
在你的主组件或任何其他地方使用这个鸿组件:
// App.js 或其他文件中
import React from 'react';
import { View } from 'react-native';
import HongComponent from './HongComponent'; // 确保路径正确
const App = () => {
return (
<View>
<HongComponent />
</View>
);
};
export default App;
步骤 5: 查看日志输出
运行你的应用:
npx react-native run-Harmony 对于Harmony设备或模拟器
npx react-native run-Harmony 对于Harmony设备或模拟器
在应用中点击“执行保养”按钮,你应该能在应用的日志输出(例如Harmony Studio的Logcat或者Xcode的Console)中看到记录的日志。同时,如果你在开发过程中使用console.log,也可以在开发控制台看到这些日志。
高级配置:自定义日志级别和存储位置react-native-logs库支持自定义日志级别和输出方式。你可以查看其文档来了解如何配置这些高级功能。例如,设置日志级别为DEBUG或ERROR等:
Logs.setLogLevel(Logs.DEBUG); // 设置日志级别为DEBUG,显示所有级别日志(包括DEBUG, INFO, WARN, ERROR)
或者将日志输出到文件等其他存储位置,这通常需要更多的配置和权限处理。对于Harmony,可能需要额外的文件写入权限;对于Harmony,则需要特定的文件管理设置。具体方法请参考react-native-logs的文档。
以上就是在React Native中开发鸿组件并实现保养日志记录的基本步骤和示例代码。根据具体需求,你可能还需要调整和优化这些步骤。
真实项目案例演示:
// app.tsx
import React, { useState } from 'react';
import { View, Text, StyleSheet, TextInput, TouchableOpacity, ScrollView, Image, Alert } from 'react-native';
const App = () => {
const [date, setDate] = useState('');
const [vehicle, setVehicle] = useState('');
const [mileage, setMileage] = useState('');
const [serviceType, setServiceType] = useState('');
const [notes, setNotes] = useState('');
const [records, setRecords] = useState<any[]>([]);
const [editingIndex, setEditingIndex] = useState<number | null>(null);
// Base64 icons
const icons = {
date: 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9IiM0Mjg1RjQiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIj48cmVjdCB4PSIzIiB5PSI0IiB3aWR0aD0iMTgiIGhlaWdodD0iMTgiIHJ4PSIyIiByeT0iMiI+PC9yZWN0PjxsaW5lIHgxPSI4IiB5MT0iMiIgeDI9IjgiIHkyPSI2Ij48L2xpbmU+PGxpbmUgeDE9IjE2IiB5MT0iMiIgeDI9IjE2IiB5Mj0iNiI+PC9saW5lPjxsaW5lIHgxPSIzIiB5MT0iMTAiIHgyPSIyMSIgeTI9IjEwIj48L2xpbmU+PHRleHQgeD0iOCIgeT0iMTQiPk1vbiBGcmk8L3RleHQ+PC9zdmc+',
car: 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9IiM0Mjg1RjQiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIj48cGF0aCBkPSJNMjAgMjF2LTlhMSAxIDAgMCAwLTEtMUg2YTEgMSAwIDAgMC0xIDF2OW0tMy00VjdoMS4yNWEzIDMgMCAwIDEgMy0zaDguNWEzIDMgMCAwIDEgMyAzaDEuMjV2MTFINiI+PC9wYXRoPjwvc3ZnPg==',
odometer: 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9IiM0Mjg1RjQiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIj48Y2lyY2xlIGN4PSIxMiIgY3k9IjEyIiByPSIxMCI+PC9jaXJjbGU+PGxpbmUgeDE9IjEyIiB5MT0iOCIgeDI9IjEyIiB5Mj0iMTIiPjwvbGluZT48bGluZSB4MT0iMTIiIHkxPSIxMiIgeDI9IjE2IiB5Mj0iMTIiPjwvbGluZT48L3N2Zz4=',
service: 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9IiM0Mjg1RjQiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIj48cGF0aCBkPSJNMTQgMkwxMCAxbC00IDEgMiA3LTMgNCAxIDJsNi0xIDMgNCAxLTIgMy00LTItN3oiPjwvcGF0aD48L3N2Zz4=',
note: 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9IiM0Mjg1RjQiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIj48cGF0aCBkPSJNMTQgMkwxMCAxbC00IDEgMiA3LTMgNCAxIDJsNi0xIDMgNCAxLTIgMy00LTItN3pNMTggMTRzLTMgNC05IDQtOS00LTMtNC05IDQtOSA0Ij48L3BhdGg+PC9zdmc+',
save: 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9IiM0Mjg1RjQiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIj48cGF0aCBkPSJNMTkgMjFINGEyIDIgMCAwIDEtMi0yVjVhMiAyIDAgMCAxIDItMmg3Ij48L3BhdGg+PHBvbHlsaW5lIHBvaW50cz0iMTcgMiA5LjUgMiA3IDcgMTcgNyAxNyAyIj48L3BvbHlsaW5lPjxsaW5lIHgxPSI5IiB5MT0HarmonyIgeDI9IjE1IiB5Mj0HarmonyI+PC9saW5lPjxsaW5lIHgxPSI5IiB5MT0iMTMiIHgyPSIxNSIgeTI9IjEzIj48L2xpbmU+PGxpbmUgeDE9IjkiIHkxPSIxNyIgeDI9IjE1IiB5Mj0iMTciPjwvbGluZT48L3N2Zz4=',
edit: 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9IiM0Mjg1RjQiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIj48cGF0aCBkPSJNMTcgM0EyIDIgMCAwIDAgMTUuNTg2IDMuNDY0TDMuNTg2IDE1LjQ2NEEyIDIgMCAwIDAgMyAyMWgyLjVhMSAxIDAgMCAwIC43MDctLjI5M2wxMi0xMkExIDIgMCAwIDAgMTcgM3oiPjwvcGF0aD48L3N2Zz4=',
delete: 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9IiNFRTQ0M0EiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIj48cGF0aCBkPSJNMTkgNlY1YTIgMiAwIDAgMC0yLTJIN2EyIDIgMCAwIDAtMiAydjEiPjwvcGF0aD48bGluZSB4MT0iOCIgeTE9IjkiIHgyPSIxNiIgeTI9IjkiPjwvbGluZT48cGF0aCBkPSJNMTkgNlYyMGEyIDIgMCAwIDEtMiAyaC04YTIgMiAwIDAgMS0yLTJWNiI+PC9wYXRoPjxyZWN0IHg9IjkiIHk9IjYiIHdpZHRoPSIxMiIgaGVpZ2h0PSIxOCIgcng9IjIiIHJ5PSIyIj48L3JlY3Q+PC9zdmc+'
};
const serviceTypes = ['机油更换', '轮胎保养', '刹车系统', '发动机保养', '空调保养', '其他'];
const handleSubmit = () => {
if (!date || !vehicle || !mileage || !serviceType) {
Alert.alert('错误', '请填写所有必填项');
return;
}
const record = {
id: Date.now(),
date,
vehicle,
mileage: parseInt(mileage),
serviceType,
notes
};
if (editingIndex !== null) {
const updatedRecords = [...records];
updatedRecords[editingIndex] = record;
setRecords(updatedRecords);
setEditingIndex(null);
Alert.alert('成功', '保养记录已更新');
} else {
setRecords([...records, record]);
Alert.alert('成功', '保养记录已保存');
}
// 清空表单
setDate('');
setVehicle('');
setMileage('');
setServiceType('');
setNotes('');
};
const handleEdit = (index: number) => {
const record = records[index];
setDate(record.date);
setVehicle(record.vehicle);
setMileage(record.mileage.toString());
setServiceType(record.serviceType);
setNotes(record.notes);
setEditingIndex(index);
};
const handleDelete = (index: number) => {
Alert.alert(
'确认删除',
'确定要删除这条保养记录吗?',
[
{ text: '取消', style: 'cancel' },
{
text: '删除',
style: 'destructive',
onPress: () => {
const updatedRecords = [...records];
updatedRecords.splice(index, 1);
setRecords(updatedRecords);
}
}
]
);
};
const clearForm = () => {
setDate('');
setVehicle('');
setMileage('');
setServiceType('');
setNotes('');
setEditingIndex(null);
};
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}>
<View style={styles.inputLabel}>
<Image source={{ uri: icons.date }} style={styles.inputIcon} />
<Text style={styles.labelText}>保养日期 *</Text>
</View>
<TextInput
style={styles.input}
value={date}
onChangeText={setDate}
placeholder="例如: 2023-10-15"
/>
</View>
<View style={styles.inputGroup}>
<View style={styles.inputLabel}>
<Image source={{ uri: icons.car }} style={styles.inputIcon} />
<Text style={styles.labelText}>车辆信息 *</Text>
</View>
<TextInput
style={styles.input}
value={vehicle}
onChangeText={setVehicle}
placeholder="品牌型号,例如: 丰田凯美瑞"
/>
</View>
<View style={styles.inputGroup}>
<View style={styles.inputLabel}>
<Image source={{ uri: icons.odometer }} style={styles.inputIcon} />
<Text style={styles.labelText}>里程数(km) *</Text>
</View>
<TextInput
style={styles.input}
value={mileage}
onChangeText={setMileage}
placeholder="例如: 50000"
keyboardType="numeric"
/>
</View>
<View style={styles.inputGroup}>
<View style={styles.inputLabel}>
<Image source={{ uri: icons.service }} style={styles.inputIcon} />
<Text style={styles.labelText}>保养项目 *</Text>
</View>
<View style={styles.serviceTypeContainer}>
{serviceTypes.map(type => (
<TouchableOpacity
key={type}
style={[
styles.serviceTypeButton,
serviceType === type && styles.selectedServiceType
]}
onPress={() => setServiceType(type)}
>
<Text style={[
styles.serviceTypeText,
serviceType === type && styles.selectedServiceTypeText
]}>
{type}
</Text>
</TouchableOpacity>
))}
</View>
</View>
<View style={styles.inputGroup}>
<View style={styles.inputLabel}>
<Image source={{ uri: icons.note }} style={styles.inputIcon} />
<Text style={styles.labelText}>备注说明</Text>
</View>
<TextInput
style={[styles.input, styles.textArea]}
value={notes}
onChangeText={setNotes}
placeholder="请输入保养详情..."
multiline
numberOfLines={4}
/>
</View>
<View style={styles.buttonContainer}>
<TouchableOpacity style={styles.saveButton} onPress={handleSubmit}>
<Image source={{ uri: icons.save }} style={styles.buttonIcon} />
<Text style={styles.saveButtonText}>
{editingIndex !== null ? '更新记录' : '保存记录'}
</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.clearButton} onPress={clearForm}>
<Text style={styles.clearButtonText}>清空</Text>
</TouchableOpacity>
</View>
</View>
<View style={styles.recordsContainer}>
<Text style={styles.recordsTitle}>保养记录 ({records.length})</Text>
{records.length === 0 ? (
<View style={styles.emptyContainer}>
<Text style={styles.emptyText}>暂无保养记录</Text>
</View>
) : (
<View style={styles.recordsList}>
{records.map((record, index) => (
<View key={record.id} style={styles.recordCard}>
<View style={styles.recordHeader}>
<Text style={styles.recordDate}>{record.date}</Text>
<Text style={styles.recordMileage}>{record.mileage.toLocaleString()} km</Text>
</View>
<Text style={styles.recordVehicle}>{record.vehicle}</Text>
<Text style={styles.recordService}>{record.serviceType}</Text>
{record.notes ? (
<Text style={styles.recordNotes}>{record.notes}</Text>
) : null}
<View style={styles.recordActions}>
<TouchableOpacity
style={styles.editButton}
onPress={() => handleEdit(index)}
>
<Image source={{ uri: icons.edit }} style={styles.actionIcon} />
<Text style={styles.editButtonText}>编辑</Text>
</TouchableOpacity>
<TouchableOpacity
style={styles.deleteButton}
onPress={() => handleDelete(index)}
>
<Image source={{ uri: icons.delete }} style={styles.actionIcon} />
<Text style={styles.deleteButtonText}>删除</Text>
</TouchableOpacity>
</View>
</View>
))}
</View>
)}
</View>
</ScrollView>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#f5f7fa',
padding: 20
},
header: {
alignItems: 'center',
marginBottom: 30,
paddingTop: 20
},
title: {
fontSize: 26,
fontWeight: 'bold',
color: '#2c3e50'
},
subtitle: {
fontSize: 16,
color: '#7f8c8d',
marginTop: 6
},
formContainer: {
backgroundColor: '#fff',
borderRadius: 16,
padding: 20,
marginBottom: 25,
elevation: 4,
shadowColor: '#000',
shadowOffset: { width: 0, height: 2 },
shadowOpacity: 0.1,
shadowRadius: 8
},
inputGroup: {
marginBottom: 20
},
inputLabel: {
flexDirection: 'row',
alignItems: 'center',
marginBottom: 10
},
inputIcon: {
width: 20,
height: 20,
marginRight: 10
},
labelText: {
fontSize: 16,
fontWeight: '600',
color: '#34495e'
},
input: {
borderWidth: 1,
borderColor: '#ddd',
borderRadius: 12,
padding: 14,
fontSize: 16,
backgroundColor: '#fafbfc'
},
textArea: {
height: 100,
textAlignVertical: 'top'
},
serviceTypeContainer: {
flexDirection: 'row',
flexWrap: 'wrap'
},
serviceTypeButton: {
backgroundColor: '#eef2f7',
borderRadius: 20,
paddingHorizontal: 16,
paddingVertical: 10,
margin: 5
},
selectedServiceType: {
backgroundColor: '#4285F4'
},
serviceTypeText: {
color: '#34495e',
fontSize: 14
},
selectedServiceTypeText: {
color: '#fff'
},
buttonContainer: {
flexDirection: 'row',
justifyContent: 'space-between',
marginTop: 10
},
saveButton: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'center',
backgroundColor: '#4285F4',
borderRadius: 12,
paddingVertical: 14,
paddingHorizontal: 20,
flex: 1,
marginRight: 10
},
buttonIcon: {
width: 20,
height: 20,
marginRight: 10
},
saveButtonText: {
color: '#fff',
fontSize: 16,
fontWeight: '600'
},
clearButton: {
backgroundColor: '#fff',
borderWidth: 1,
borderColor: '#ddd',
borderRadius: 12,
paddingVertical: 14,
paddingHorizontal: 20,
flex: 1,
marginLeft: 10,
alignItems: 'center'
},
clearButtonText: {
color: '#7f8c8d',
fontSize: 16,
fontWeight: '600'
},
recordsContainer: {
backgroundColor: '#fff',
borderRadius: 16,
padding: 20,
elevation: 4,
shadowColor: '#000',
shadowOffset: { width: 0, height: 2 },
shadowOpacity: 0.1,
shadowRadius: 8
},
recordsTitle: {
fontSize: 22,
fontWeight: 'bold',
color: '#2c3e50',
marginBottom: 20,
textAlign: 'center'
},
emptyContainer: {
paddingVertical: 40,
alignItems: 'center'
},
emptyText: {
color: '#95a5a6',
fontSize: 16
},
recordsList: {
gap: 15
},
recordCard: {
backgroundColor: '#fafbfc',
borderRadius: 12,
padding: 16,
borderWidth: 1,
borderColor: '#eef2f7'
},
recordHeader: {
flexDirection: 'row',
justifyContent: 'space-between',
marginBottom: 10
},
recordDate: {
fontSize: 16,
fontWeight: '600',
color: '#4285F4'
},
recordMileage: {
fontSize: 16,
fontWeight: '600',
color: '#34495e'
},
recordVehicle: {
fontSize: 18,
fontWeight: 'bold',
color: '#2c3e50',
marginBottom: 8
},
recordService: {
fontSize: 16,
color: '#34495e',
marginBottom: 8
},
recordNotes: {
fontSize: 14,
color: '#7f8c8d',
marginBottom: 15,
fontStyle: 'italic'
},
recordActions: {
flexDirection: 'row',
justifyContent: 'flex-end'
},
editButton: {
flexDirection: 'row',
alignItems: 'center',
backgroundColor: '#4285F4',
borderRadius: 8,
paddingHorizontal: 12,
paddingVertical: 8,
marginRight: 10
},
deleteButton: {
flexDirection: 'row',
alignItems: 'center',
backgroundColor: '#EE443A',
borderRadius: 8,
paddingHorizontal: 12,
paddingVertical: 8
},
actionIcon: {
width: 16,
height: 16,
marginRight: 6
},
editButtonText: {
color: '#fff',
fontSize: 14
},
deleteButtonText: {
color: '#fff',
fontSize: 14
}
});
export default App;
这段React Native车辆保养日志代码实现了一个完整的车辆维护记录管理系统,其核心原理基于React的状态管理和表单处理机制。handleDelete函数通过Alert.alert创建确认对话框,采用destructive样式强调删除操作的危险性,这种设计模式符合鸿蒙系统的用户交互规范。函数内部使用展开运算符创建记录数组副本,通过splice方法移除指定索引的记录,避免直接修改原数组,这种不可变数据处理方式在鸿蒙系统的状态管理中具有重要意义。
从鸿蒙系统适配角度来看,该代码充分利用了React Native的跨平台特性,在鸿蒙设备上能够获得原生级的性能表现。鸿蒙系统的分布式数据管理能力与React的状态提升概念高度契合,records状态作为单一数据源确保了数据一致性。保养记录的增删改查操作通过localStorage或AsyncStorage实现数据持久化,在鸿蒙系统的多设备协同场景中能够保证数据同步。
表单处理逻辑通过多个useState钩子管理各个输入字段状态,clearForm函数将所有字段重置为空值并清除编辑状态。这种状态管理模式在鸿蒙系统的应用生命周期管理中非常重要,能够确保组件在不同使用场景下的状态一致性。handleSubmit函数根据editingIndex状态判断是新增还是更新操作,通过Date.now()生成唯一ID,这种设计在鸿蒙系统的数据唯一性要求中具有实际价值。

UI布局采用ScrollView作为根容器,确保内容在不同屏幕尺寸设备上的可滚动性。保养项目选择区域通过TouchableOpacity组件实现标签式选择,每个选项根据选中状态应用不同样式,这种交互设计符合鸿蒙系统的UI规范。TextInput组件通过keyboardType属性指定数字键盘,提升用户输入效率,在鸿蒙系统的输入法适配中能够获得更好的体验。
记录列表区域通过map方法遍历records数组,每个记录项包含日期、里程数、车辆信息和保养项目等关键数据。记录卡片采用垂直布局,顶部显示日期和里程数,中部显示车辆信息,底部显示保养项目和备注。这种信息架构在鸿蒙系统的健康数据展示中非常常见,能够帮助用户快速获取关键信息。
编辑功能通过设置editingIndex状态实现,当用户点击编辑按钮时,将选中记录的数据填充到表单中,保存按钮文本动态显示为"更新记录"。这种设计在鸿蒙系统的表单处理中具有重要意义,能够提供直观的操作反馈。删除功能通过索引定位记录并移除,在鸿蒙系统的批量数据处理场景中能够提供良好的性能表现。
打包
接下来通过打包命令npn run harmony将reactNative的代码打包成为bundle,这样可以进行在开源鸿蒙OpenHarmony中进行使用。

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

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

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



所有评论(0)