React Native实现一个简单的多级列表(复制即可用)

774 阅读1分钟

要在React Native中实现类似于Element UI的el-table功能,可以使用ScrollView和自定义样式来创建表格布局,并通过渲染数据来填充表格。

一级列表.jpg 二级列表.jpg 三级列表.jpg

代码如下

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>
  );
}