You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何在Antd Table外部添加搜索筛选并关联表格搜索功能?

实现Antd Table外部全局搜索+列内搜索的结合方案

没问题!你已经搭建好了列内的搜索筛选功能,现在要添加表格外的全局搜索,只需要在现有代码基础上做几个小改动,就能让全局搜索和列筛选同时生效,还能保留关键词高亮效果。下面是具体的实现步骤和修改后的完整代码:

核心改动点

  • 新增globalSearchText状态变量,专门存储全局搜索的关键词
  • 给表格外的Input绑定事件,实时更新全局搜索状态
  • 对数据源做双重过滤:先应用全局搜索规则,再保留列筛选的结果
  • 调整高亮逻辑,让全局搜索和列内搜索的关键词都能被高亮

修改后的完整代码

import React from "react";
import ReactDOM from "react-dom";
import "antd/dist/antd.css";
import "./index.css";
import { Table, Input, Button, Icon } from "antd";
import Highlighter from "react-highlight-words";

const data = [
  { key: "1", name: "John Brown", age: 32, address: "New York No. 1 Lake Park" },
  { key: "2", name: "Joe Black", age: 42, address: "London No. 1 Lake Park" },
  { key: "3", name: "Jim Green", age: 32, address: "Sidney No. 1 Lake Park" },
  { key: "4", name: "Jim Red", age: 32, address: "London No. 2 Lake Park" }
];

class App extends React.Component {
  // 新增全局搜索状态
  state = { sRT: "", globalSearchText: "" };

  getColumnSearchProps = dataIndex => ({
    filterDropdown: ({ setSelectedKeys, selectedKeys, confirm, clearFilters }) => (
      <div style={{ padding: 8 }}>
        <Input
          placeholder={`Search ${dataIndex}`}
          onChange={e => setSelectedKeys(e.target.value ? [e.target.value] : [])}
          onPressEnter={() => this.handleSearch(selectedKeys, confirm)}
          style={{ width: 188, marginBottom: 8, display: "block" }}
          ref={node => (this.searchInput = node)}
        />
        <Button
          type="primary"
          onClick={() => this.handleSearch(selectedKeys, confirm)}
          icon="search"
          size="small"
          style={{ width: 90, marginRight: 8 }}
        >
          Search
        </Button>
        <Button onClick={() => this.handleReset(clearFilters)} size="small" style={{ width: 90 }}>
          Reset
        </Button>
      </div>
    ),
    filterIcon: filtered => (
      <Icon type="search" style={{ color: filtered ? "#1890ff" : undefined }} />
    ),
    onFilter: (value, record) =>
      record[dataIndex]
        .toString()
        .toLowerCase()
        .includes(value.toLowerCase()),
    onFilterDropdownVisibleChange: visible => {
      if (visible) {
        setTimeout(() => this.searchInput.select());
      }
    },
    render: text => {
      // 合并全局搜索和列搜索的关键词,去重后一起高亮
      const highlightWords = [...new Set([this.state.sRT, this.state.globalSearchText].filter(Boolean))];
      return (
        <Highlighter
          highlightStyle={{ backgroundColor: "#ffc069", padding: 0 }}
          searchWords={highlightWords}
          autoEscape
          textToHighlight={text.toString()}
        />
      );
    }
  });

  handleSearch = (selectedKeys, confirm) => {
    confirm();
    this.setState({ sRT: selectedKeys[0] });
  };

  handleReset = clearFilters => {
    clearFilters();
    this.setState({ sRT: "" });
  };

  // 处理全局搜索输入的实时更新
  handleGlobalSearchChange = (e) => {
    this.setState({ globalSearchText: e.target.value });
  };

  render() {
    const columns = [
      {
        title: "Name",
        dataIndex: "name",
        key: "name",
        width: "30%",
        ...this.getColumnSearchProps("name")
      },
      {
        title: "Age",
        dataIndex: "age",
        key: "age",
        width: "20%",
        ...this.getColumnSearchProps("age")
      },
      {
        title: "Address",
        dataIndex: "address",
        key: "address",
        ...this.getColumnSearchProps("address")
      }
    ];

    // 双重过滤:先全局搜索缩小范围,再交给Table处理列筛选
    const filteredData = data.filter(item => {
      if (!this.state.globalSearchText) return true;
      const searchText = this.state.globalSearchText.toLowerCase();
      // 检查当前数据的所有字段是否包含全局搜索关键词
      return Object.values(item).some(val => 
        val.toString().toLowerCase().includes(searchText)
      );
    });

    return (
      <div>
        {/* 全局搜索输入框,绑定实时更新事件 */}
        <Input 
          type="text" 
          placeholder="Global Search" 
          value={this.state.globalSearchText}
          onChange={this.handleGlobalSearchChange}
          style={{ marginBottom: 16, width: 300 }}
          prefix={<Icon type="search" />}
        />
        {/* 传入经过全局过滤后的数据源 */}
        <Table columns={columns} dataSource={filteredData} />
        <br />
      </div>
    );
  }
}

ReactDOM.render(<App />, document.getElementById("container"));

关键逻辑说明

  1. 全局搜索过滤:在render函数中先对原始数据做一次全局过滤,只保留包含全局搜索关键词的数据,再将其传给Table,这样全局搜索会先缩小数据范围,再结合列的筛选逻辑,确保两种搜索互不冲突。
  2. 高亮合并:在列的渲染函数里,把全局搜索和列搜索的关键词去重合并,传给Highlighter组件,这样两个搜索的关键词都会被高亮显示。
  3. 状态独立管理:全局搜索和列搜索的状态分开存储,操作时互不影响,你可以单独使用全局搜索、单独使用列筛选,也可以同时使用两种功能。

这样修改后,你就能同时拥有表格外的全局搜索和表格内的列搜索功能啦!

内容的提问来源于stack exchange,提问作者Amanda

火山引擎 最新活动