返回

鼠标拖动 + Ctrl 选中多个表格行

前端

在处理复杂的用户界面交互时,如鼠标拖动并使用 Ctrl 键选中多个表格行,需要细致地监听和处理多种事件。本文将详细介绍如何实现这一功能,并提供相应的代码示例和操作步骤。

问题背景

实现鼠标拖动选中多个表格行的功能,本质上是通过监听鼠标事件来实现的。需要监听鼠标按下、移动和松开这三个事件,并根据不同的事件类型做出相应的处理。通过将鼠标按下的坐标和松开的坐标进行比较,我们可以确定用户拖动选中的范围。如果用户在拖动过程中按下了 Ctrl 键,那么我们需要将之前选中的行与当前拖动选中的行合并。最后,我们需要更新表格中的选中状态,以反映用户的选择。

实现步骤

1. 安装依赖

首先,确保你已经安装了必要的依赖包。这里我们使用 antd 作为示例:

npm install antd

2. 引入 Ant Design Vue

在你的项目中引入 antdTable 组件:

import { Table } from 'antd';

3. 监听鼠标按下事件

在表格组件中监听鼠标按下事件,保存鼠标按下的坐标:

const handleMouseDown = (event) => {
  const { clientX, clientY } = event;
  setSelectedRange({
    start: {
      x: clientX,
      y: clientY,
    },
    end: {
      x: clientX,
      y: clientY,
    },
  });
};

4. 监听鼠标移动事件

在表格组件中监听鼠标移动事件,根据鼠标按下的坐标和当前鼠标的坐标计算出拖动选中的范围:

const handleMouseMove = (event) => {
  const { clientX, clientY } = event;
  setSelectedRange({
    start: {
      x: selectedRange.start.x,
      y: selectedRange.start.y,
    },
    end: {
      x: clientX,
      y: clientY,
    },
  });
};

5. 更新表格中的选中状态

根据鼠标移动的范围更新表格中的选中状态:

const updateSelection = () => {
  const { start, end } = selectedRange;
  const rows = tableData.filter((row) => {
    const { x, y } = row;
    return x >= start.x && x <= end.x && y >= start.y && y <= end.y;
  });
  setSelectedRows(rows);
};

6. 监听鼠标松开事件

在表格组件中监听鼠标松开事件,如果用户在拖动过程中按下了 Ctrl 键,那么我们将之前选中的行与当前拖动选中的行合并:

const handleMouseUp = (event) => {
  if (event.ctrlKey) {
    const rows = [...selectedRows, ...selectedRange];
    setSelectedRows(rows);
  }
};

7. 更新表格中的选中状态

最后,我们更新表格中的选中状态,以反映用户的选择:

useEffect(() => {
  updateSelection();
}, [selectedRange]);

完整示例代码

以下是一个完整的示例代码,展示了如何实现上述功能:

import React, { useState, useEffect } from 'react';
import { Table } from 'antd';

const MyTable = ({ tableData }) => {
  const [selectedRange, setSelectedRange] = useState({
    start: {
      x: 0,
      y: 0,
    },
    end: {
      x: 0,
      y: 0,
    },
  });
  const [selectedRows, setSelectedRows] = useState([]);

  const handleMouseDown = (event) => {
    const { clientX, clientY } = event;
    setSelectedRange({
      start: {
        x: clientX,
        y: clientY,
      },
      end: {
        x: clientX,
        y: clientY,
      },
    });
  };

  const handleMouseMove = (event) => {
    const { clientX, clientY } = event;
    setSelectedRange({
      start: {
        x: selectedRange.start.x,
        y: selectedRange.start.y,
      },
      end: {
        x: clientX,
        y: clientY,
      },
    });
  };

  const handleMouseUp = (event) => {
    if (event.ctrlKey) {
      const rows = [...selectedRows, ...selectedRange];
      setSelectedRows(rows);
    }
  };

  useEffect(() => {
    updateSelection();
  }, [selectedRange]);

  const updateSelection = () => {
    const { start, end } = selectedRange;
    const rows = tableData.filter((row) => {
      const { x, y } = row;
      return x >= start.x && x <= end.x && y >= start.y && y <= end.y;
    });
    setSelectedRows(rows);
  };

  const columns = [
    // 定义你的列配置
  ];

  return (
    <Table
      components={{
        body: {
          cell: EditableCell,
        },
      }}
      dataSource={tableData}
      onMouseDown={handleMouseDown}
      onMouseMove={handleMouseMove}
      onMouseUp={handleMouseUp}
      style={{ margin: '20px' }}
    >
      {columns.map((col) => (
        <Table.Column key={col.dataIndex} title={col.title} dataIndex={col.dataIndex} />
      ))}
    </Table>
  );
};

const EditableCell = ({
  editing,
  dataIndex,
  title,
  inputType,
  record,
  index,
  children,
  ...restProps
}) => {
  const inputNode = inputType === 'number' ? <Input.Number /> : <Input />;
  return (
    <td {...restProps}>
      {editing ? (
        <Form.Item
          name={dataIndex}
          style={{
            margin: 0,
          }}
          rules={[
            {
              required: true,
              message: `请输入 ${title}!`,
            },
          ]}
        >
          {inputNode}
        </Form.Item>
      ) : (
        children
      )}
    </td>
  );
};

export default MyTable;

相关资源链接

通过上述步骤和代码示例,你可以实现一个功能完善的鼠标拖动 + Ctrl 选中多个表格行的功能。希望本文对你有所帮助!