要在React Native中实现类似于Element UI的el-table功能,可以使用ScrollView和自定义样式来创建表格布局,并通过渲染数据来填充表格。
代码如下
import React, { useState } from 'react';
import { View, Text, ScrollView, TouchableOpacity, StyleSheet } from 'react-native';
const data = [
{
id: 1,
name: 'Category 1',
age: 1,
children: [
{
id: 11,
name: 'Item 1-1',
age: 11,
children: [
{ id: 111, name: 'subItem 1-1-1', age: 111 },
{ id: 121, name: 'subItem 1-2-1', age: 121 },
],
},
{ id: 12, name: 'Item 1-2', age: 12 },
],
},
{
id: 2,
age: 2,
name: 'Category 2',
children: [
{ id: 21, name: 'Item 2-1', age: 21 },
{ id: 22, name: 'Item 2-2', age: 22 },
],
},
];
const columns = [
{ key: 'id', title: 'ID' },
{ key: 'name', title: 'Name' },
{ key: 'age', title: 'Age' },
];
const TreeNode = ({ columns, node, level }) => {
const [expanded, setExpanded] = useState(false);
const toggleExpand = () => {
setExpanded(!expanded);
};
const renderNode = (node) => {
return (
<View style={styles.row}>
{columns?.map((col, index) => {
if (index === 0) {
return (
<TouchableOpacity style={{ flex: 1 }} onPress={toggleExpand}>
<Text style={[styles.cell, { paddingLeft: level * 8 }]}>{node?.[col?.key]}</Text>
</TouchableOpacity>
);
} else {
return <Text style={{ flex: 1 }}>{node?.[col?.key]}</Text>;
}
})}
</View>
);
};
if (!node.children) {
return renderNode(node);
}
return (
<View style={styles.container}>
{renderNode(node)}
{expanded &&
node?.children?.map((child) => <TreeNode key={child.id} node={child} level={level + 1} columns={columns} />)}
</View>
);
};
const Table = ({ columns, data }) => {
return (
<ScrollView style={styles.scrollView}>
<View style={styles.headerRow}>
{columns.map((column) => (
<Text key={column.key} style={styles.headerCell}>
{column.title}
</Text>
))}
</View>
{data?.map((node) => (
<TreeNode key={node.id} node={node} level={0} columns={columns} />
))}
</ScrollView>
);
};
const styles = StyleSheet.create({
scrollView: {
flex: 1,
padding: 16,
marginTop: 50,
},
container: {
marginTop: 8,
},
row: {
flexDirection: 'row',
alignItems: 'center',
borderBottomWidth: 1,
borderBottomColor: '#ccc',
paddingVertical: 8,
},
cell: {
flex: 1,
paddingHorizontal: 8,
},
headerRow: {
flexDirection: 'row',
borderBottomWidth: 1,
borderBottomColor: '#ccc',
marginBottom: 8,
},
headerCell: {
flex: 1,
fontWeight: 'bold',
},
});
export default function App() {
return (
<View style={{ flex: 1 }}>
<Table data={data} columns={columns} />
</View>
);
}