为什么React Native中的表这么难?

brc7rcf0  于 2022-12-27  发布在  React
关注(0)|答案(2)|浏览(131)

我试图在React Native中重新创建html表功能,但我无法解决这个问题。
我有一列用于项目名称(短),另一列用于项目描述(可能很长)。

**我希望第一列只占用它所需要的空间,第二列可以伸缩,当它用完空间时,文本换行。**这部分很简单,但是第一列中的项目都有不同的宽度。如果我把列放在第一位来解决这个问题,那么让第一列中的对应项垂直伸缩以保持对齐就让我犯了个错误。2 HTML表格可以毫不费力地做到这一点。3为什么在Native中这么难呢?

在这种语言中真的没有办法做一个真正灵活的表吗?
我尝试了flex的不同变体,但是我不希望它是任何一列的固定宽度或比率,因为我想稍后保留字体大小选项,这会破坏它。
react-native-paper失败是因为DataTable.Cell不允许多行,并且添加功能会扰乱对齐,这又让我回到了开始的地方。

**EDIT:**在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>

导致:

7uhlpewt

7uhlpewt1#

您可以创建一个名为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'看起来更好,但当然我不知道你的先决条件是什么。
要使用数据填充表,需要向表组件传递一个项目数组。要执行此操作,请修改表组件

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;

这将用数据填充您的表。

2ul0zpep

2ul0zpep2#

好的,我想我得到了我想要的功能,可能有一种更可扩展的方法来做到这一点,这可能是非常低效的,但它似乎工作。
要点是,我可以使用一个状态变量来存储每个单元格所需的宽度,然后在onLayout中,每当布局发生变化时,我可以调用setColWidth来更新该变量,然后,我可以使用style将最小宽度设置为最大单元格的宽度。
还有一个数组,用于确定是否收缩给定列以给其他列留出空间。
最后,我可以在父级View中调用alignItems,将表收缩到适合数据的最小大小

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 emulator showing the working code
现在,我能看到的唯一问题是,它不更新时,从横向旋转到纵向(但纵向到横向工程罚款???)

相关问题