React Click/Mouse 事件处理 [react-sortable-hoc, material-ui, react-virtualized]

React Click/Mouse Event Handling [react-sortable-hoc, material-ui, react-virtualized]

我有下面的例子

Stackblitz Live Working Example

如果您按下红色垃圾箱图标上的删除按钮,它不会触发我的 onClick 事件处理程序(而是立即开始排序)。

如果您按下按钮的删除按钮背景(垃圾箱图标周围的圆圈),它会触发按钮 onClick 处理程序并执行相应操作。

我试过设置不同的 onClick(包括 xxxxCapture 版本和 e.preventDefault())但没有成功。

问题

因此我有两个问题:

  1. 有没有一种好方法可以找出树中首先处理点击的位置?
  2. 如何使我的按钮 onClick 在背景中以及 icon 本身保持一致?

代码

对于无法打开 Stackblitz 的人,代码是:

import React from 'react';
import { Button, IconButton, Tooltip, Typography } from "@material-ui/core";

import { Add, DeleteForever } from "@material-ui/icons";
import { AutoSizer, Column, Index, Table, TableCellProps, TableProps, TableRowProps, WindowScroller, defaultTableRowRenderer } from "react-virtualized";
import { SortableContainer, SortableElement, SortEnd, SortEndHandler, SortEvent } from "react-sortable-hoc";


import 'react-virtualized/styles.css';

const SortableTable = SortableContainer<TableProps>((props: TableProps) => (
  <Table {...props} />
));

const SortableRow = SortableElement<TableRowProps>(
  (props: TableRowProps) => defaultTableRowRenderer(props) as any
);

const sortableRowRenderer = (props: TableRowProps) => {
  return <SortableRow {...props} />;
};

interface IRow {
  value: string;
}

class Grid extends React.Component<any, { items: IRow[] }> {

  remove(rowData: any): any {
    const items = this.state.items;

    if (!items) {
      return;
    }

    const index = items.indexOf(rowData);

    const newItems = [...items.slice(0, index), ...items.slice(index + 1)];

    this.setState({ items: newItems });
  }

  constructor(props: any) {
    super(props);

    this.state = {
      items: this.getDefaultItems()
    };
  }

  private getDefaultItems = () => {
    return [
      { value: "one" },
      { value: "two" },
      { value: "three" },
      { value: "four" },
      { value: "five" }
    ]
  }

  private rowRenderer = (props: TableRowProps) => {
    return defaultTableRowRenderer(props);
  };

  public render() {
    return (
      <div>
        <WindowScroller>
          {({ height, isScrolling, onChildScroll, scrollTop }) => (
            <AutoSizer disableHeight={true}>
              {size => (
                <SortableTable
                  headerHeight={38}
                  autoHeight={true}
                  height={height}
                  rowCount={this.state.items.length}
                  scrollTop={scrollTop}
                  rowGetter={this.getItem}
                  rowHeight={37}
                  width={size.width}
                  rowRenderer={sortableRowRenderer}
                >
                  <Column label={"value"} dataKey={"value"} width={160} />
                  <Column
                    dataKey={"buttons"}
                    cellRenderer={this.buttonsCellRenderer}
                    width={48}
                    minWidth={48}
                    maxWidth={48}
                  />
                </SortableTable>
              )}
            </AutoSizer>
          )}
        </WindowScroller>
        <Button onClick={this.reset}>Reset</Button>
      </div>
    );
  }

  private reset = () => {
    this.setState({ items: this.getDefaultItems() });
  }

  private buttonsCellRenderer = (props: TableCellProps) => {
    const remove = (event: any) => {
      console.log("remove");
      console.log(event);

      this.remove(props.rowData);
    };

    const removeWithPrevent = (event: any) => {
      console.log("removeWithPrevent");
      console.log(event);

      this.remove(props.rowData);
    };

    return (
      <Tooltip title="Delete Line Item" enterDelay={500}>
        <IconButton onClick={remove}>
          <DeleteForever fontSize="small" color="error" onClick={remove} />
        </IconButton>
      </Tooltip>
    );
  };

  private getItem = (info: Index) => {
    const rows = this.state.items;

    const row = rows[info.index];

    return row;
  };
}

export default Grid;

我正在开发同类应用程序,当我单击单元格上的某些内容并使它们可排序时,我想执行一些操作。它可以通过两种方式实现

  1. 在 SortableContainer HOC 中添加延迟属性 pressDelay 属性。 docs 假设 pressDelay=500。这将做的是,如果你按住你的点击 500 毫秒,该行将变得可排序,否则只是正常的点击事件 fire.in 我认为这会很好

2.add 行首的句柄,只需拖动句柄即可排序。为此,您需要实施 customTableRowRenderer。只需从此处复制代码 rowRenderer 并从 sortable hoc 导入句柄,然后更改 return 函数

  import { SortableHandle } from 'react-sortable-hoc';

     const DragHandle = SortableHandle(() => columns[0]);
      return (
        <div
          {...a11yProps}
          className={className}
          key={key}
          role='row'
          style={style}>
          <DragHandle />
          {columns.slice(1, columns.length)}
        </div>
      );

不要忘记将句柄添加为第一列。