利用状态管理、持久化存储或者利用现有的库来辅助React Native鸿蒙跨平台开发开发一个允许用户撤销删除的操作

在 React Native 中,实现一个类似 Windows 回收站的功能(即允许用户撤销删除的操作)可以通过多种方式实现,例如使用状态管理、持久化存储或者利用现有的库来辅助。下面我将介绍几种常见的方法来实现这样一个功能:

  1. 使用状态管理

最直接的方法是使用 React 的状态(state)来管理组件的删除状态。你可以创建一个数组来存储所有组件的列表,并在删除时将组件标记为已删除但暂时不从数组中移除。

示例代码:

import React, { useState } from 'react';
import { View, Text, Button, FlatList } from 'react-native';
const RecycleBin = ({ items, onDelete, onUndo }) => {
return (
<FlatList
data={items}
keyExtractor={item => item.id}
renderItem={({ item }) => (
<View>
  <Text>{item.name}</Text>
    <Button title="撤销" onPress={() => onUndo(item.id)} />
      </View>
        )}
        />
        );
        };
        const App = () => {
        const [items, setItems] = useState([
        { id: '1', name: 'Item 1' },
        { id: '2', name: 'Item 2' },
        { id: '3', name: 'Item 3' }
        ]);
        const [deletedItems, setDeletedItems] = useState([]);
        const handleDelete = (id) => {
        const item = items.find(item => item.id === id);
        setDeletedItems(prev => [...prev, item]);
        setItems(items.filter(item => item.id !== id));
        };
        const handleUndo = (id) => {
        const item = deletedItems.find(item => item.id === id);
        setDeletedItems(deletedItems.filter(item => item.id !== id));
        setItems(prev => [...prev, item]);
        };
        return (
        <View>
          <FlatList
          data={items}
          keyExtractor={item => item.id}
          renderItem={({ item }) => (
          <View>
            <Text>{item.name}</Text>
              <Button title="删除" onPress={() => handleDelete(item.id)} />
                </View>
                  )}
                  />
                  <RecycleBin items={deletedItems} onUndo={handleUndo} />
                    </View>
                      );
                      };
                      export default App;
  1. 使用持久化存储(如 AsyncStorage)

对于需要持久化存储删除项的情况,可以使用 AsyncStorage 来保存删除的项。这样即使在应用重启后,用户也可以从回收站恢复已删除的项。

示例代码:

import AsyncStorage from '@react-native-async-storage/async-storage';
import { useState, useEffect } from 'react';
import { View, Text, Button, FlatList } from 'react-native';
const App = () => {
const [items, setItems] = useState([]);
const [deletedItems, setDeletedItems] = useState([]);
const [isLoading, setIsLoading] = useState(true); // 控制加载状态,防止在数据加载完成前渲染组件导致错误。
useEffect(() => {
const loadData = async () => {
try {
const storedItems = await AsyncStorage.getItem('items'); // 假设之前已经存储了数据。
const storedDeletedItems = await AsyncStorage.getItem('deletedItems'); // 假设之前已经存储了数据。
if (storedItems !== null) { setItems(JSON.parse(storedItems)); }
if (storedDeletedItems !== null) { setDeletedItems(JSON.parse(storedDeletedItems)); }
} catch (e) { console.log(e); } finally { setIsLoading(false); } // 加载完成后设置加载状态为false。 避免在数据加载完成前渲染组件。 
};
loadData(); // 调用加载数据的函数。 每次组件挂载时都会尝试加载数据。 可以在卸载组件时清除这些数据以节省空间。 例如:componentWillUnmount(){} 中使用 AsyncStorage.clear()。 但在Hooks中使用时,可以使用useEffect的清理函数。 例如:return () => AsyncStorage.clear(); }。

真实实际场景代码:

// app.tsx
import React, { useState } from 'react';
import { SafeAreaView, View, Text, StyleSheet, TouchableOpacity, ScrollView, Modal, Alert } from 'react-native';
// Base64 图标库
const ICONS = {
trash: 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0id2hpdGUiPjxwYXRoIGQ9Ik02IDhoMTJ2MTJhMiAyIDAgMDEtMiAyaC04YTIgMiAwIDAxLTItMlY4eiIvPjxwYXRoIGQ9Ik00IDZoMTZ2Mkg0eiIvPjxwYXRoIGQ9Ik0xMCAxMXY2aDJ2LTZoLTJ6Ii8+PHBhdGggZD0iTTE0IDExdjZoMnYtNkgxNHoiLz48cGF0aCBkPSJNMTAgN2gydjJoLTJWN3oiLz48L3N2Zz4=',
restore: 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0id2hpdGUiPjxwYXRoIGQ9Ik0xMiA4djRoLTZ2LTZoMnYyaDR6Ii8+PHBhdGggZD0iTTEyIDE0djRoNnYtMmgtMnYtMmgtNHoiLz48cGF0aCBkPSJNMTIgMTB2LTRoLTJ2NGgtNHYyaDR2Mmg0di0yaC00eiIvPjxwYXRoIGQ9Ik02IDE0aC0ydjJoMnYyaDJ2LTJoMnYtMkg2di0yeiIvPjxwYXRoIGQ9Ik0xOCAxMGgydi0yaC0ydi0yaC0ydjJoLTJ2Mmg0eiIvPjxwYXRoIGQ9Ik02IDZoMTJ2MTJINlY2eiIvPjwvc3ZnPg==',
delete: 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0id2hpdGUiPjxwYXRoIGQ9Ik02IDE5YzAgMS4xLjkgMiAyIDJoOGMxLjEgMCAyLS45IDItMlY3SDZ2MTJ6bTgtMTBoLTR2LTJoNHYyaDB6Ii8+PHBhdGggZD0iTTE4IDRoLTR2MWgtNHYtMUg2Yy0xLjEgMC0yIC45LTIgMnYxYzAgLjYgMSAxLjUgMSAyaDE0YzAgLS41IDEtMS40IDEtMlY2YzAtMS4xLTEuOS0yLTItMnoiLz48L3N2Zz4=',
file: 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0id2hpdGUiPjxwYXRoIGQ9Ik02IDJoMTJ2Nmw2IDZ2MTJINlYyeiIvPjxwYXRoIGQ9Ik0xNCAyaDJ2Nmg2bC02LTZ6Ii8+PC9zdmc+',
image: 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0id2hpdGUiPjxwYXRoIGQ9Ik04LjUgMTMuNWwyLjUgMyAzLjUtNC41IDQuNSA2SDVtMTYtMTVIM2MtMS4xIDAtMiAuOS0yIDJ2MTRjMCAxLjEuOSAyIDIgMmgxOGMxLjEgMCAyLS45IDItMlY2YzAtMS4xLS45LTItMi0yeiIvPjwvc3ZnPg==',
document: 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0id2hpdGUiPjxwYXRoIGQ9Ik0xNCAyaC00djJoLTR2MmgxMlY0aC00VjJ6bS00IDZoMTJ2MUgxMHYtMXptMCAyaDEydjFINTB2LTF6bTAgMmgxMnYxSDEwdi0xem0wIDJoMTJ2MUgxMHYtMXoiLz48L3N2Zz4=',
folder: 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0id2hpdGUiPjxwYXRoIGQ9Ik0xMCA0SDRjLTEuMSAwLTIgLjktMiAydjEyYzAgMS4xLjkgMiAyIDJoMTZjMS4xIDAgMi0uOSAyLTJWNmMwLTEuMS0uOS0yLTItMmgtOGwtLTItMnoiLz48L3N2Zz4=',
empty: 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0id2hpdGUiPjxwYXRoIGQ9Ik0xMiA1LjY5Yy0uMzYgMC0uNy4wNS0xLjA2LjEzbDEuNTkgMS41OGMuMDUuMDUuMTMuMDQuMTgtLjAybDEuNTktMS41OGMuMDUtLjA1LjA0LS4xMy0uMDItLjE4Yy0uMzUtLjA4LS43LS4xMy0xLjA2LS4xM3oiLz48cGF0aCBkPSJNMTIgMkM2LjQ4IDIgMiA2LjQ4IDIgMTJzNC40OCAxMCAxMCAxMCAxMC00LjQ4IDEwLTEwUzE3LjUyIDIgMTIgMnptMCAxOGMtNC40MSAwLTgtMy41OS04LThzMy41OS04IDgtOCA4IDMuNTkgOCA4LTMuNTkgOC04IDgiLz48L3N2Zz4=',
close: 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0id2hpdGUiPjxwYXRoIGQ9Ik0xOSA2LjQxTDE3LjU5IDUgMTIgMTAuNTkgNi40MSA1IDUgNi40MSAxMC41OSAxMiA1IDE3LjU5IDYuNDEgMTkgMTIgMTMuNDEgMTcuNTkgMTkgMTkgMTcuNTkgMTMuNDEgMTJ6Ii8+PC9zdmc+'
};
// 默认文件数据
const DEFAULT_FILES = [
{ id: '1', name: '项目报告.docx', type: 'document', size: '2.4 MB', deletedAt: '2023-06-15 14:30' },
{ id: '2', name: '度假照片.jpg', type: 'image', size: '5.1 MB', deletedAt: '2023-06-14 09:15' },
{ id: '3', name: '财务报表.xlsx', type: 'document', size: '1.2 MB', deletedAt: '2023-06-13 16:45' },
{ id: '4', name: '工作资料', type: 'folder', size: '15.7 MB', deletedAt: '2023-06-12 11:20' },
];
const RecycleBin: React.FC = () => {
const [files, setFiles] = useState(DEFAULT_FILES);
const [selectedFile, setSelectedFile] = useState<any>(null);
  const [modalVisible, setModalVisible] = useState(false);
  // 获取文件图标
  const getFileIcon = (fileType: string) => {
  switch (fileType) {
  case 'image': return ICONS.image;
  case 'document': return ICONS.document;
  case 'folder': return ICONS.folder;
  default: return ICONS.file;
  }
  };
  // 获取文件图标颜色
  const getFileIconColor = (fileType: string) => {
  switch (fileType) {
  case 'image': return '#45B7D1';
  case 'document': return '#4361ee';
  case 'folder': return '#f72585';
  default: return '#6c757d';
  }
  };
  // 恢复文件
  const restoreFile = (id: string) => {
  setFiles(files.filter(file => file.id !== id));
  Alert.alert('恢复成功', '文件已恢复到原来位置');
  };
  // 彻底删除文件
  const permanentlyDeleteFile = (id: string) => {
  Alert.alert(
  '彻底删除',
  '确定要彻底删除这个文件吗?此操作无法撤销。',
  [
  { text: '取消', style: 'cancel' },
  {
  text: '删除',
  style: 'destructive',
  onPress: () => {
  setFiles(files.filter(file => file.id !== id));
  Alert.alert('删除成功', '文件已彻底删除');
  }
  }
  ]
  );
  };
  // 清空回收站
  const clearRecycleBin = () => {
  if (files.length === 0) {
  Alert.alert('提示', '回收站已经是空的');
  return;
  }
  Alert.alert(
  '清空回收站',
  `确定要彻底删除回收站中的全部${files.length}个项目吗?`,
  [
  { text: '取消', style: 'cancel' },
  {
  text: '清空',
  style: 'destructive',
  onPress: () => {
  setFiles([]);
  Alert.alert('清空成功', '回收站已清空');
  }
  }
  ]
  );
  };
  // 查看文件详情
  const viewFileDetails = (file: any) => {
  setSelectedFile(file);
  setModalVisible(true);
  };
  return (
  <SafeAreaView style={styles.container}>
    <View style={styles.header}>
      <View style={styles.headerTop}>
        <Text style={styles.title}>回收站</Text>
          <TouchableOpacity
          style={styles.clearButton}
          onPress={clearRecycleBin}
          disabled={files.length === 0}
          >
          <Text style={[styles.clearButtonText, files.length === 0 && styles.disabledText]}>清空</Text>
            </TouchableOpacity>
              </View>
                <Text style={styles.subtitle}>已删除的文件将在此保留30</Text>
                  <View style={styles.statsContainer}>
                    <View style={styles.statBox}>
                      <Text style={styles.statNumber}>{files.length}</Text>
                        <Text style={styles.statLabel}>项目</Text>
                          </View>
                            <View style={styles.statBox}>
                              <Text style={styles.statNumber}>
                                {files.reduce((total, file) => {
                                const size = parseFloat(file.size);
                                return total + (isNaN(size) ? 0 : size);
                                }, 0).toFixed(1)} MB
                                </Text>
                                  <Text style={styles.statLabel}>占用空间</Text>
                                    </View>
                                      </View>
                                        </View>
                                          <ScrollView contentContainerStyle={styles.content}>
                                            {files.length === 0 ? (
                                            <View style={styles.emptyContainer}>
                                              <Text style={styles.emptyIcon}>{decodeURIComponent(escape(atob(ICONS.empty.split(',')[1])))}</Text>
                                                <Text style={styles.emptyText}>回收站为空</Text>
                                                  <Text style={styles.emptySubtext}>没有找到已删除的文件</Text>
                                                    </View>
                                                      ) : (
                                                      files.map((file) => (
                                                      <View key={file.id} style={styles.fileCard}>
                                                        <View style={styles.fileInfo}>
                                                          <Text style={[styles.fileIcon, { color: getFileIconColor(file.type) }]}>
                                                            {decodeURIComponent(escape(atob(getFileIcon(file.type).split(',')[1])))}
                                                            </Text>
                                                              <View style={styles.fileDetails}>
                                                                <Text style={styles.fileName}>{file.name}</Text>
                                                                  <Text style={styles.fileMeta}>{file.size} · {file.deletedAt}</Text>
                                                                    </View>
                                                                      </View>
                                                                        <View style={styles.fileActions}>
                                                                          <TouchableOpacity
                                                                          style={[styles.actionButton, styles.restoreButton]}
                                                                          onPress={() => restoreFile(file.id)}
                                                                          >
                                                                          <Text style={styles.restoreIcon}>
                                                                            {decodeURIComponent(escape(atob(ICONS.restore.split(',')[1])))}
                                                                            </Text>
                                                                              <Text style={styles.actionText}>恢复</Text>
                                                                                </TouchableOpacity>
                                                                                  <TouchableOpacity
                                                                                  style={[styles.actionButton, styles.deleteButton]}
                                                                                  onPress={() => permanentlyDeleteFile(file.id)}
                                                                                  >
                                                                                  <Text style={styles.deleteIcon}>
                                                                                    {decodeURIComponent(escape(atob(ICONS.delete.split(',')[1])))}
                                                                                    </Text>
                                                                                      <Text style={styles.actionText}>删除</Text>
                                                                                        </TouchableOpacity>
                                                                                          <TouchableOpacity
                                                                                          style={[styles.actionButton, styles.infoButton]}
                                                                                          onPress={() => viewFileDetails(file)}
                                                                                          >
                                                                                          <Text style={styles.infoIcon}>...</Text>
                                                                                            </TouchableOpacity>
                                                                                              </View>
                                                                                                </View>
                                                                                                  ))
                                                                                                  )}
                                                                                                  </ScrollView>
                                                                                                    {/* 文件详情模态框 */}
                                                                                                    <Modal
                                                                                                    animationType="slide"
                                                                                                    transparent={true}
                                                                                                    visible={modalVisible}
                                                                                                    onRequestClose={() => setModalVisible(false)}
                                                                                                    >
                                                                                                    <View style={styles.modalOverlay}>
                                                                                                      <View style={styles.modalContent}>
                                                                                                        <View style={styles.modalHeader}>
                                                                                                          <Text style={styles.modalTitle}>文件详情</Text>
                                                                                                            <TouchableOpacity onPress={() => setModalVisible(false)}>
                                                                                                              <Text style={styles.closeButton}>×</Text>
                                                                                                                </TouchableOpacity>
                                                                                                                  </View>
                                                                                                                    {selectedFile && (
                                                                                                                    <View style={styles.modalBody}>
                                                                                                                      <Text style={[styles.detailIcon, { color: getFileIconColor(selectedFile.type) }]}>
                                                                                                                        {decodeURIComponent(escape(atob(getFileIcon(selectedFile.type).split(',')[1])))}
                                                                                                                        </Text>
                                                                                                                          <Text style={styles.detailName}>{selectedFile.name}</Text>
                                                                                                                            <View style={styles.detailRow}>
                                                                                                                              <Text style={styles.detailLabel}>文件类型:</Text>
                                                                                                                                <Text style={styles.detailValue}>{selectedFile.type}</Text>
                                                                                                                                  </View>
                                                                                                                                    <View style={styles.detailRow}>
                                                                                                                                      <Text style={styles.detailLabel}>文件大小:</Text>
                                                                                                                                        <Text style={styles.detailValue}>{selectedFile.size}</Text>
                                                                                                                                          </View>
                                                                                                                                            <View style={styles.detailRow}>
                                                                                                                                              <Text style={styles.detailLabel}>删除时间:</Text>
                                                                                                                                                <Text style={styles.detailValue}>{selectedFile.deletedAt}</Text>
                                                                                                                                                  </View>
                                                                                                                                                    </View>
                                                                                                                                                      )}
                                                                                                                                                      <View style={styles.modalActions}>
                                                                                                                                                        <TouchableOpacity
                                                                                                                                                        style={[styles.modalButton, styles.modalRestoreButton]}
                                                                                                                                                        onPress={() => {
                                                                                                                                                        restoreFile(selectedFile?.id);
                                                                                                                                                        setModalVisible(false);
                                                                                                                                                        }}
                                                                                                                                                        >
                                                                                                                                                        <Text style={styles.modalButtonText}>恢复文件</Text>
                                                                                                                                                          </TouchableOpacity>
                                                                                                                                                            <TouchableOpacity
                                                                                                                                                            style={[styles.modalButton, styles.modalDeleteButton]}
                                                                                                                                                            onPress={() => {
                                                                                                                                                            permanentlyDeleteFile(selectedFile?.id);
                                                                                                                                                            setModalVisible(false);
                                                                                                                                                            }}
                                                                                                                                                            >
                                                                                                                                                            <Text style={styles.modalButtonText}>彻底删除</Text>
                                                                                                                                                              </TouchableOpacity>
                                                                                                                                                                </View>
                                                                                                                                                                  </View>
                                                                                                                                                                    </View>
                                                                                                                                                                      </Modal>
                                                                                                                                                                        </SafeAreaView>
                                                                                                                                                                          );
                                                                                                                                                                          };
                                                                                                                                                                          const styles = StyleSheet.create({
                                                                                                                                                                          container: {
                                                                                                                                                                          flex: 1,
                                                                                                                                                                          backgroundColor: '#f8f9fa',
                                                                                                                                                                          },
                                                                                                                                                                          header: {
                                                                                                                                                                          paddingTop: 30,
                                                                                                                                                                          paddingBottom: 20,
                                                                                                                                                                          paddingHorizontal: 20,
                                                                                                                                                                          backgroundColor: '#ffffff',
                                                                                                                                                                          borderBottomWidth: 1,
                                                                                                                                                                          borderBottomColor: '#e9ecef',
                                                                                                                                                                          },
                                                                                                                                                                          headerTop: {
                                                                                                                                                                          flexDirection: 'row',
                                                                                                                                                                          justifyContent: 'space-between',
                                                                                                                                                                          alignItems: 'center',
                                                                                                                                                                          marginBottom: 8,
                                                                                                                                                                          },
                                                                                                                                                                          title: {
                                                                                                                                                                          fontSize: 24,
                                                                                                                                                                          fontWeight: 'bold',
                                                                                                                                                                          color: '#212529',
                                                                                                                                                                          },
                                                                                                                                                                          clearButton: {
                                                                                                                                                                          paddingVertical: 6,
                                                                                                                                                                          paddingHorizontal: 12,
                                                                                                                                                                          borderRadius: 6,
                                                                                                                                                                          backgroundColor: '#e9ecef',
                                                                                                                                                                          },
                                                                                                                                                                          clearButtonText: {
                                                                                                                                                                          fontSize: 14,
                                                                                                                                                                          color: '#495057',
                                                                                                                                                                          fontWeight: '600',
                                                                                                                                                                          },
                                                                                                                                                                          disabledText: {
                                                                                                                                                                          color: '#adb5bd',
                                                                                                                                                                          },
                                                                                                                                                                          subtitle: {
                                                                                                                                                                          fontSize: 14,
                                                                                                                                                                          color: '#6c757d',
                                                                                                                                                                          marginBottom: 15,
                                                                                                                                                                          },
                                                                                                                                                                          statsContainer: {
                                                                                                                                                                          flexDirection: 'row',
                                                                                                                                                                          backgroundColor: '#e9ecef',
                                                                                                                                                                          borderRadius: 12,
                                                                                                                                                                          padding: 15,
                                                                                                                                                                          },
                                                                                                                                                                          statBox: {
                                                                                                                                                                          flex: 1,
                                                                                                                                                                          alignItems: 'center',
                                                                                                                                                                          },
                                                                                                                                                                          statNumber: {
                                                                                                                                                                          fontSize: 18,
                                                                                                                                                                          fontWeight: 'bold',
                                                                                                                                                                          color: '#212529',
                                                                                                                                                                          },
                                                                                                                                                                          statLabel: {
                                                                                                                                                                          fontSize: 14,
                                                                                                                                                                          color: '#6c757d',
                                                                                                                                                                          marginTop: 4,
                                                                                                                                                                          },
                                                                                                                                                                          content: {
                                                                                                                                                                          padding: 16,
                                                                                                                                                                          },
                                                                                                                                                                          emptyContainer: {
                                                                                                                                                                          alignItems: 'center',
                                                                                                                                                                          justifyContent: 'center',
                                                                                                                                                                          paddingVertical: 60,
                                                                                                                                                                          },
                                                                                                                                                                          emptyIcon: {
                                                                                                                                                                          fontSize: 64,
                                                                                                                                                                          color: '#ced4da',
                                                                                                                                                                          marginBottom: 20,
                                                                                                                                                                          },
                                                                                                                                                                          emptyText: {
                                                                                                                                                                          fontSize: 20,
                                                                                                                                                                          fontWeight: '600',
                                                                                                                                                                          color: '#495057',
                                                                                                                                                                          marginBottom: 8,
                                                                                                                                                                          },
                                                                                                                                                                          emptySubtext: {
                                                                                                                                                                          fontSize: 16,
                                                                                                                                                                          color: '#6c757d',
                                                                                                                                                                          },
                                                                                                                                                                          fileCard: {
                                                                                                                                                                          backgroundColor: '#ffffff',
                                                                                                                                                                          borderRadius: 12,
                                                                                                                                                                          padding: 16,
                                                                                                                                                                          marginBottom: 12,
                                                                                                                                                                          elevation: 2,
                                                                                                                                                                          shadowColor: '#000',
                                                                                                                                                                          shadowOffset: { width: 0, height: 2 },
                                                                                                                                                                          shadowOpacity: 0.08,
                                                                                                                                                                          shadowRadius: 4,
                                                                                                                                                                          },
                                                                                                                                                                          fileInfo: {
                                                                                                                                                                          flexDirection: 'row',
                                                                                                                                                                          alignItems: 'center',
                                                                                                                                                                          marginBottom: 15,
                                                                                                                                                                          },
                                                                                                                                                                          fileIcon: {
                                                                                                                                                                          fontSize: 28,
                                                                                                                                                                          marginRight: 15,
                                                                                                                                                                          },
                                                                                                                                                                          fileDetails: {
                                                                                                                                                                          flex: 1,
                                                                                                                                                                          },
                                                                                                                                                                          fileName: {
                                                                                                                                                                          fontSize: 16,
                                                                                                                                                                          fontWeight: '600',
                                                                                                                                                                          color: '#212529',
                                                                                                                                                                          marginBottom: 4,
                                                                                                                                                                          },
                                                                                                                                                                          fileMeta: {
                                                                                                                                                                          fontSize: 14,
                                                                                                                                                                          color: '#6c757d',
                                                                                                                                                                          },
                                                                                                                                                                          fileActions: {
                                                                                                                                                                          flexDirection: 'row',
                                                                                                                                                                          justifyContent: 'space-between',
                                                                                                                                                                          },
                                                                                                                                                                          actionButton: {
                                                                                                                                                                          flexDirection: 'row',
                                                                                                                                                                          alignItems: 'center',
                                                                                                                                                                          paddingVertical: 8,
                                                                                                                                                                          paddingHorizontal: 12,
                                                                                                                                                                          borderRadius: 6,
                                                                                                                                                                          },
                                                                                                                                                                          restoreButton: {
                                                                                                                                                                          backgroundColor: '#d1fae5',
                                                                                                                                                                          },
                                                                                                                                                                          deleteButton: {
                                                                                                                                                                          backgroundColor: '#fee2e2',
                                                                                                                                                                          },
                                                                                                                                                                          infoButton: {
                                                                                                                                                                          backgroundColor: '#e0f2fe',
                                                                                                                                                                          },
                                                                                                                                                                          restoreIcon: {
                                                                                                                                                                          fontSize: 16,
                                                                                                                                                                          color: '#10b981',
                                                                                                                                                                          marginRight: 6,
                                                                                                                                                                          },
                                                                                                                                                                          deleteIcon: {
                                                                                                                                                                          fontSize: 16,
                                                                                                                                                                          color: '#ef4444',
                                                                                                                                                                          marginRight: 6,
                                                                                                                                                                          },
                                                                                                                                                                          infoIcon: {
                                                                                                                                                                          fontSize: 16,
                                                                                                                                                                          color: '#0ea5e9',
                                                                                                                                                                          },
                                                                                                                                                                          actionText: {
                                                                                                                                                                          fontSize: 14,
                                                                                                                                                                          fontWeight: '600',
                                                                                                                                                                          },
                                                                                                                                                                          modalOverlay: {
                                                                                                                                                                          flex: 1,
                                                                                                                                                                          backgroundColor: 'rgba(0, 0, 0, 0.5)',
                                                                                                                                                                          justifyContent: 'center',
                                                                                                                                                                          alignItems: 'center',
                                                                                                                                                                          },
                                                                                                                                                                          modalContent: {
                                                                                                                                                                          backgroundColor: '#ffffff',
                                                                                                                                                                          width: '85%',
                                                                                                                                                                          borderRadius: 20,
                                                                                                                                                                          padding: 25,
                                                                                                                                                                          },
                                                                                                                                                                          modalHeader: {
                                                                                                                                                                          flexDirection: 'row',
                                                                                                                                                                          justifyContent: 'space-between',
                                                                                                                                                                          alignItems: 'center',
                                                                                                                                                                          marginBottom: 20,
                                                                                                                                                                          },
                                                                                                                                                                          modalTitle: {
                                                                                                                                                                          fontSize: 20,
                                                                                                                                                                          fontWeight: 'bold',
                                                                                                                                                                          color: '#212529',
                                                                                                                                                                          },
                                                                                                                                                                          closeButton: {
                                                                                                                                                                          fontSize: 30,
                                                                                                                                                                          color: '#adb5bd',
                                                                                                                                                                          fontWeight: '200',
                                                                                                                                                                          },
                                                                                                                                                                          modalBody: {
                                                                                                                                                                          alignItems: 'center',
                                                                                                                                                                          marginBottom: 25,
                                                                                                                                                                          },
                                                                                                                                                                          detailIcon: {
                                                                                                                                                                          fontSize: 48,
                                                                                                                                                                          marginBottom: 15,
                                                                                                                                                                          },
                                                                                                                                                                          detailName: {
                                                                                                                                                                          fontSize: 18,
                                                                                                                                                                          fontWeight: '600',
                                                                                                                                                                          color: '#212529',
                                                                                                                                                                          marginBottom: 20,
                                                                                                                                                                          },
                                                                                                                                                                          detailRow: {
                                                                                                                                                                          flexDirection: 'row',
                                                                                                                                                                          justifyContent: 'space-between',
                                                                                                                                                                          width: '100%',
                                                                                                                                                                          marginBottom: 12,
                                                                                                                                                                          },
                                                                                                                                                                          detailLabel: {
                                                                                                                                                                          fontSize: 16,
                                                                                                                                                                          color: '#6c757d',
                                                                                                                                                                          },
                                                                                                                                                                          detailValue: {
                                                                                                                                                                          fontSize: 16,
                                                                                                                                                                          color: '#212529',
                                                                                                                                                                          fontWeight: '600',
                                                                                                                                                                          },
                                                                                                                                                                          modalActions: {
                                                                                                                                                                          flexDirection: 'row',
                                                                                                                                                                          justifyContent: 'space-between',
                                                                                                                                                                          },
                                                                                                                                                                          modalButton: {
                                                                                                                                                                          flex: 1,
                                                                                                                                                                          paddingVertical: 12,
                                                                                                                                                                          borderRadius: 8,
                                                                                                                                                                          alignItems: 'center',
                                                                                                                                                                          marginHorizontal: 5,
                                                                                                                                                                          },
                                                                                                                                                                          modalRestoreButton: {
                                                                                                                                                                          backgroundColor: '#10b981',
                                                                                                                                                                          },
                                                                                                                                                                          modalDeleteButton: {
                                                                                                                                                                          backgroundColor: '#ef4444',
                                                                                                                                                                          },
                                                                                                                                                                          modalButtonText: {
                                                                                                                                                                          fontSize: 16,
                                                                                                                                                                          fontWeight: '600',
                                                                                                                                                                          color: '#ffffff',
                                                                                                                                                                          },
                                                                                                                                                                          });
                                                                                                                                                                          export default RecycleBin;

这段代码实现了一个回收站管理界面,主要用于文件管理应用中的已删除文件管理功能。从鸿蒙开发的角度来看,这个组件体现了现代移动应用开发中的核心设计理念。

在数据结构设计上,DEFAULT_FILES数组采用了ID、名称、类型、大小和删除时间的组合方式来定义文件对象。这种设计在鸿蒙应用开发中同样适用,鸿蒙的ArkTS语言支持类似的对象数组结构,可以使用interface来定义文件对象的类型结构,确保数据的一致性和类型安全。鸿蒙开发中推荐使用资源管理机制来处理图标,将图标文件放置在resources目录下,通过$r(‘app.media.icon_name’)方式引用。

在状态管理方面,React使用useState来维护组件状态,包括文件列表、选中文件、模态框显示状态等。鸿蒙开发中可以使用@State装饰器实现类似的状态管理机制,通过状态变量的变更来驱动UI的自动更新。鸿蒙的声明式UI框架同样具有高效的渲染机制,通过状态变化自动计算最小渲染代价来更新界面。

UI布局采用了卡片列表设计,通过ScrollView容器展示文件卡片。在鸿蒙开发中,可以使用Column和Row组合配合ForEach循环渲染来实现类似的列表布局效果。每个文件卡片包含了文件信息展示区和操作按钮区,这种模块化的设计便于维护和扩展。

请添加图片描述

文件图标处理根据文件类型动态选择不同的图标和颜色,这种设计在鸿蒙应用中同样重要。鸿蒙支持通过条件渲染来实现类似的功能,根据文件类型动态绑定不同的图标资源和样式属性。颜色管理方面,为不同文件类型指定了特定的主题色,这在鸿蒙应用中可以通过资源文件统一管理颜色值。

模态框的实现体现了良好的用户体验设计,通过透明遮罩来突出操作焦点。鸿蒙系统提供了丰富的弹窗组件,可以实现更加原生和一致的用户交互体验。文件详情查看功能可以通过鸿蒙的Sheet组件或者自定义弹窗来实现。

数据持久化方面,虽然代码中没有直接体现,但在实际应用中会将回收站数据存储在本地或云端。鸿蒙提供了多种数据存储方案,包括Preferences轻量级数据存储、KVStore分布式数据存储等,可以根据应用需求选择合适的存储方式。

在交互设计上,恢复文件和彻底删除操作都提供了确认机制,防止误操作。鸿蒙系统有内置的AlertDialog组件,可以提供更加原生和一致的用户交互体验。清空回收站功能通过批量操作来提高用户效率,这种设计在鸿蒙应用中同样适用。

统计信息展示区域显示了回收站中的项目数量和占用空间,这种数据可视化在鸿蒙应用中可以通过Text组件结合状态计算来实现。鸿蒙支持响应式布局,可以根据屏幕尺寸自动调整统计信息的展示方式。

文件操作方面,恢复和删除功能通过过滤数组来更新文件列表,这种数据处理方式在鸿蒙开发中同样适用。鸿蒙的数组操作API提供了丰富的函数式编程支持,可以实现类似的文件管理逻辑。

空状态处理通过条件渲染展示空回收站提示,这种用户体验设计在鸿蒙应用中同样重要。鸿蒙支持通过if-else条件渲染来实现不同的界面状态,确保用户在任何情况下都有清晰的操作指引。


打包

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

在这里插入图片描述

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

在这里插入图片描述

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

请添加图片描述

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

posted @ 2026-01-15 17:01  yangykaifa  阅读(0)  评论(0)    收藏  举报