如何在 React Native 中重新创建 html 表格功能?

问题描述 投票:0回答:2

我正在尝试在 React Native 中重新创建 html 表功能,但我无法弄清楚这一点。

我有 1 列用于项目名称(短),另一列用于项目描述(可能很长)。

我希望第一列只占用所需的空间,第二列可以弯曲,然后在空间不足时自动换行。这部分很简单,但是第一列中的项目都有不同的宽度。如果我首先制作列来解决这个问题,那么让第一列中的相应项目垂直弯曲以保持对齐就会让我绊倒。 HTML 表格可以毫不费力地做到这一点。为什么 Native 这么难?

真的没有办法用这种语言做一个真正灵活的表格吗?

我已经尝试了不同的 Flex 变体,但是 我不希望它成为任一列的固定宽度或比例,因为我想稍后保留字体大小的选项,这会破坏它。

react-native-paper
失败,因为
DataTable.Cell
不允许多行,并且添加功能会扰乱对齐,让我回到开始的地方。

编辑:在html中,我会这样做:

<html>
    <head>
        <style>
            td:first-child {white-space: nowrap; }
        </style>
    </head>
    <body>
        <table>
            <tr>
                <td>
                    I am some data!
                </td>
                <td>
                    Two households, both alike in dignity, in fair Verona, where we lay our scene, from ancient grudge break to new mutiny, where civil blood makes civil hands unclean.
                </td>
            </tr>
            <tr>
                <td>
                    I'm data too!
                </td>
                <td>
                    From forth the fatal loins of these two foes, a pair of star-cross'd lovers take their life; whose misadventured piteous overthrows do with their death bury their parents' strife.
                </td>
            </tr>
            <tr>
                <td>
                    I am also some data!
                </td>
                <td>
                    The fearful passage of their death-mark'd love, and the continuance of their parents' rage, which, but their children's end, nought could remove, is now the two hours' traffic of our stage; the which if you with patient ears attend, what here shall miss, our toil shall strive to mend.
                </td>
            </tr>
        </table>
    </body>
</html>

结果:

enter image description here

react-native
2个回答
0
投票

您可以创建一个名为

Table
的组件(代表表格本身)和一个名为
TableRow
的组件(代表表格的一行)。

import React from 'react';
import { View } from 'react-native';
import TableRow from './TableRow';

const Table = () => (
  <View style={{ flexDirection: 'column' }}>
    <TableRow itemName="Item 1" itemDescription="Description for item 1" />
    <TableRow itemName="Item 2" itemDescription="Description for item 2" />
    <TableRow itemName="Item 3" itemDescription="Description for item 3" />
  </View>
);

export default Table;

import React from 'react';
import { View, Text } from 'react-native';

const TableRow = ({ itemName, itemDescription }) => (
  <View style={{ flexDirection: 'row' }}>
    <View style={{ width: 'auto', alignItems: 'flex-start' }}>
      <Text>{itemName}</Text>
    </View>
    <View style={{ flex: 3, alignItems: 'flex-start' }}>
      <Text>{itemDescription}</Text>
    </View>
  </View>
);

export default TableRow;

在我看来,使用

flex: 1
而不是
width: 'auto'
看起来更好,但我当然不知道你的先决条件是什么。

要使用数据填充表格,您需要向表格组件传递一个项目数组。为此,请修改 Table 组件

import React from 'react';
import { View } from 'react-native';
import TableRow from './TableRow';

const Table = ({ items }) => (
  <View style={{ flexDirection: 'column' }}>
    {items.map(item => (
      <TableRow
        key={item.name}
        itemName={item.name}
        itemDescription={item.description}
      />
    ))}
  </View>
);

export default Table;

现在您可以执行以下操作:

import React from 'react';
import Table from './Table';

const items = [
  { name: 'Item 1', description: 'Description for item 1' },
  { name: 'Item 2', description: 'Description for item 2' },
  { name: 'Item 3', description: 'Description for item 3' },
];

const App = () => (
  <Table items={items} />
);

export default App;

这将用数据填充您的表格。


0
投票

好吧,我想我已经得到了我想要的功能。可能有一种更可扩展的方法来做到这一点,这可能效率极低,但它似乎有效。

要点是我可以使用状态变量来存储每个单元格所需的宽度,然后在

onLayout
中,我可以在布局更改时调用
setColWidth
来更新该变量。然后,我可以使用 style 将最小宽度设置为最大单元格的宽度。

然后有一个数组,用于确定给定列是否缩小以为其他列留出空间。

最后,我可以在父级

alignItems
中调用
View
将表收缩到适合数据的最小大小

import React, {useState} from 'react';
import {LayoutChangeEvent, useWindowDimensions, View} from 'react-native';

const Table = ({
  data,
  rowStyle = undefined,
  priviledge = new Array(data.length).fill(false),
}: {
  data: any[];
  rowStyle: Object | undefined;
  priviledge: boolean[];
}) => {
  // Initialize list of widths
  const [colWidth, setColWidth] = useState<number[][]>(
    data.map(row => new Array(Object.keys(row).length).fill(0)),
  );

  // Get widows size
  const maxSize = useWindowDimensions();

  if (!colWidth || !maxSize) {
    return <></>;
  }

  // Fix issues of going off screen
  const onLayout = (event: LayoutChangeEvent, row: number, col: number) => {
    // Get current width
    var {width, __} = event.nativeEvent.layout;

    // Find total row width
    const sum =
      colWidth[row].reduce((partialSum, a) => partialSum + a, 0) -
      colWidth[row][col] +
      width;

    // Shrink unpriviledged components
    if (!priviledge[col] && sum > maxSize.width) {
      width = width - (sum - maxSize.width);
      if (width < 0) {
        width = 0;
      }
    }

    // Store width in colWidth array
    colWidth[row][col] = width;
    setColWidth([...colWidth]);
  };

  return (
    <View>
      {/* Map along rows */}
      {data.map((item, rowIndex) => (
        <View
          key={rowIndex}
          style={{
            flexDirection: 'row',
            maxWidth: maxSize.width,
          }}>
          {/* Map along columns */}
          {Object.keys(item).map((key, colIndex) => (
            <View
              key={key}
              onLayout={event => {
                onLayout(event, rowIndex, colIndex);
              }}
              style={{
                minWidth: Math.max(...colWidth.map(row => row[colIndex])),
                flexShrink: 1,
                ...rowStyle,
              }}>
              {item[key]}
            </View>
          ))}
        </View>
      ))}
    </View>
  );
};

export default Table;

这是我的项目中的一些示例数据的外观(黄色框是使用此代码的表格):

Android 模拟器显示工作代码

现在,我看到的唯一问题是从横向旋转到纵向时它不会更新(但纵向到横向效果很好???)。

© www.soinside.com 2019 - 2024. All rights reserved.