如何在 React 中创建可排序的表?如何从排序的对象访问类方法?

Posted

技术标签:

【中文标题】如何在 React 中创建可排序的表?如何从排序的对象访问类方法?【英文标题】:How to create a sortable table in React? How to access class method from the sorted objects? 【发布时间】:2019-07-27 16:01:45 【问题描述】:

我有一个对象数组。我想访问对象函数属性中的类方法。如何实施?请帮我。我是这样写的:

render()        
  tableTh = [
    name: i18n.t('ExtendedModalBar.naming'), style:,  handleSort () ,
      ...
  ]
  ...

我正在尝试这样写:

class Table extends Component 

  handleSort() 

  
  ...

  render() 
  


我的表头是动态形成的:

<thead>
  <tr>
    <th style= width: "50px" >
      <Checkbox
        checked=this.state.selectedAll
        onChange=() => this.selectAll()
      />
    </th>
    tableTh.map((obj, index) => 
      return (
        <th key=index.toString() style=obj.style onClick=obj.handleSort>
          obj.name
        </th>
      );
    )
  </tr>
</thead>        

我必须实现表格列的排序。如果表格是静态形成的,则很容易将 onclick 附加到标签。但如果代码是这样写的,我就卡住了。如何在类中编写可从对象内部属性(对象数组)访问的方法?我需要在升序和降序两个方向上进行排序。当我单击表头时,我的表列应该改变自己的排序方向。任何答案都将被考虑在内。提前致谢

【问题讨论】:

有什么特殊原因需要这样编写代码吗?我认为更好的方法是在您的 Table 类中使用 handleSort,然后在 onClick 侦听器中将对象传递给它:() =&gt; this.handleSort(obj) 因为不是我的代码,而且有很多表,我之前的“handleSort”函数接受两个参数,columnName 和 dataToSort。我将此功能附加到表格的每一列。但在这种情况下,如何将特定列与特定数据进行排序? 看看这个codesandbox.io/embed/6lmk0q3w5z?fontsize=14 【参考方案1】:

在状态本身上具有状态更改功能的问题在于,这固有地使得操作状态变得困难。

var data = [
   name: 'a', change: /* ??? */ ,
   name: 'b', change: /* ??? */ ,
   name: 'c', change: /* ??? */ 
]

// How do we write the function ??? to change the order of data?

在更高级别(数据本身之外)提升数据操作逻辑要简单得多。

在这种情况下,我们会将数据操作逻辑放在类本身而不是在每个项目中。

我们可以通过在 React 中利用 state 来做到这一点。

状态用于保存组件的任何(动态)表示(渲染)数据。动态(不断变化的)展示数据的一个示例是对其列进行排序的表格。

我们想要将展示数据放入状态的原因是因为 React 允许我们重新触发展示(通过重新渲染)以始终显示我们数据的最新值。

我们可以通过更改数据本身而不是任何表示逻辑来实现这一点。这就是为什么 React 组件结构被称为declarative。

每当状态更新时,React 都会调用render 函数来获取具有最新状态更改的组件结构,并将其显示在适当的介质上(在您的情况下为DOM)

这是一种合并状态以创建可排序表的方法:

class Table extends React.Component 
  constructor(props) 
    super(props);

    this.state = 
      sortDirection: "asc", // we start with ascending order by default
      selectedHeaderIndex: 0 // we start by sorting based on the first header (the one in position 0)
    ;

    this.ascComparator = (row1, row2) =>
      row1[this.state.selectedHeaderIndex].localeCompare(
        row2[this.state.selectedHeaderIndex]
      );

    this.descComparator = (row1, row2) =>
      row2[this.state.selectedHeaderIndex].localeCompare(
        row1[this.state.selectedHeaderIndex]
      );

    this.flipSortDirection = () =>
      this.state.sortDirection === "asc" ? "desc" : "asc";
  

  render() 
    const  headers, rows  = this.props.table;

    const comparator =
      this.state.sortDirection === "asc"
        ? this.ascComparator
        : this.descComparator;

    // sort the rows based on the selected header
    const sortedRows = rows.sort(comparator);

    return (
      <table>
        <thead>
          headers.map((header, i) => (
            <th
              onClick=() => 
                this.setState(
                  // if we clicked on the already selected index, we flip the sort direction
                  sortDirection:
                    this.state.selectedHeaderIndex === i
                      ? this.flipSortDirection()
                      : "asc",
                  selectedHeaderIndex: i
                );
              
            >
              header
            </th>
          ))
        </thead>
        <tbody>
          sortedRows.map(row => (
            <tr>
              row.map(cell => (
                <td>cell</td>
              ))
            </tr>
          ))
        </tbody>
      </table>
    );
  


const table = 
  headers: ["h1", "h2", "h3"],
  rows: [["a", "9", "+"], ["b", "6", "-"], ["c", "3", "="]]
;

ReactDOM.render(<Table table=table />, document.querySelector("#app"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="app"></div>

使用hooks,代码变得更易读(click for the CodeSandbox example,因为 SO 还不支持 React 16.8):

function Table( table ) 
  const  headers, rows  = table;

  const [selectedHeaderIndex, setSelectedHeaderIndex] = React.useState(0); // we start by sorting based on the first header (the one in position 0)
  const [sortDirection, setSortDirection] = React.useState("asc"); // we start with ascending order by default

  // determine the sorting comparator based on the sorting direction
  const comparator =
    sortDirection === "asc"
      ? (row1, row2) =>
          row1[selectedHeaderIndex].localeCompare(row2[selectedHeaderIndex])
      : (row1, row2) =>
          row2[selectedHeaderIndex].localeCompare(row1[selectedHeaderIndex]);

  const flipSortDirection = () => (sortDirection === "asc" ? "desc" : "asc");

  // sort the rows based on the selected header
  const sortedRows = rows.sort(comparator);

  return (
    <table>
      <thead>
        headers.map((header, i) => (
          <th
            onClick=() => 
              setSelectedHeaderIndex(i);
              setSortDirection(
                selectedHeaderIndex === i ? flipSortDirection() : "asc"
              );
            
          >
            header
          </th>
        ))
      </thead>
      <tbody>
        sortedRows.map(row => (
          <tr>
            row.map(cell => (
              <td>cell</td>
            ))
          </tr>
        ))
      </tbody>
    </table>
  );


const table = 
  headers: ["h1", "h2", "h3"],
  rows: [["a", "9", "+"], ["b", "6", "-"], ["c", "3", "="]]
;

ReactDOM.render(<Table table=table />, document.querySelector("#root"));

【讨论】:

我忘了说我需要在升序和降序两个方向上进行排序。如何实施?当我点击表格标题时,我的表格列应该改变自己的排序方向。 感谢您的回答。但是现在,它不会双向排序。它依次排序,这有点不正确 之所以在构造函数中写它是因为使用箭头函数处理this绑定更简单。您绝对可以在类本身上移动这些功能,但请确保您 bind the context properly. 我什么都明白了,但我仍然无法实现排序,因为事实上,我的表格数据位于另一个组件中的组件之外。当我单击选择项目按钮时,元素表会出现在模式窗口中。如何从另一个组件获取这些数据?例如在另一个组件中:代码是:selectedItems=this.state.modalItems modalItems:this.state.devices。另一个组件导入 modalBar,我的表格在其中呈现 另一个组件中的所有 dataToSort。它导入并使用我的表所在的 modalWindow 组件。如何对这些数据进行排序如何获取它们?我必须能够在模态窗口中对表格列进行排序【参考方案2】:

将标题的点击处理程序从onClick=obj.handleSort 更改为onClick=e =&gt; handleSort(columnName, sortDirection)columnNamesortedDirection 的值是从父组件传下来的

Table 组件中的handleSort 将能够接受参数columnNamesortDirection 来操作数据。

查看此示例实现

https://codesandbox.io/embed/6lmk0q3w5z?fontsize=14

【讨论】:

以上是关于如何在 React 中创建可排序的表?如何从排序的对象访问类方法?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用React过滤和排序相同的表数据?

如何在 uiimagepickercontroller 中创建可裁剪的横幅图像?

如何在 HTML/Javascript 中创建可编辑的组合框?

如何像在 Eclipse 中一样在 IntelliJ 中创建可运行的 JAR

如何像在 Eclipse 中一样在 IntelliJ 中创建可运行的 JAR

如何在 vuetify 中创建可滚动的 v-list?