React + TSX + Ant Design 实现表格内嵌搜索框

该代码示例展示了如何在React中使用antd库创建一个动态表格组件DynamicTable,该组件支持内置搜索功能。通过在数据源中添加输入框,实现了对表格数据的即时搜索。版本2.0改进了搜索条件,支持多条件同时搜索。
摘要由CSDN通过智能技术生成

没有实现不了的功能 所见即所得 

要实现上面的功能也不需要有什么准备 既然都来到这里了 就说明环境上面的你已经搭建完成了 只是为了能实现功能

版本1.0 

新建问价DynamicTable.tsx 当然这里是作为组件来说的

引入所用得到的组件功能API   当前所用的antd版本为5.x ,请注意属性兼容!!!

import { Input, Table } from 'antd';
import { useCallback, useMemo, useState } from 'react';

定义组件名称 接收参数 DynamicTable (props里面的数据以及列项不确定直接写Array<any>)

dataSource:数据   columns:列项 这就简单得显示出一个表格

const DynamicTable = (props: { dataSource: Array<any>; columns: Array<any> }) => {
  const { dataSource, columns } = props
  return (
    <Table
      className="DynamicTable"
      dataSource={dataSource}
      bordered={true}
      tableLayout={'fixed'}
      columns={columns}
      pagination={{
        total: dataSource.length,
        showTotal: total => `共 ${total} 条`,
        showSizeChanger: true,
        showQuickJumper: true,
        pageSizeOptions: [10, 50, 100, 1000]
      }}
  
    />
  )
}

export default DynamicTable

内嵌搜索框也就是添加到表格的第一行,首行。那就直接在数据上面做手脚,将搜索框input添加到数据列表中并且位于之首。dataSource[0](仅代表个人想法,也不会有人蠢到去第二页再进行搜索)

在父组件进行使用,给父组件初始化数据  

import { useEffect, useMemo, useState } from 'react'
import DynamicTable from '../../components/DynamicTable'

const ManagePage = () => {
  const [dataSource, setdataSource] = useState<any[]>([ ])
  const [columns, setcolumns] = useState<any[]>([ ])
  useEffect(() => {
    const data = []
    for (let i = 0; i < 100; i++) {
      data.push({
        key: `${i}i`,
        name: `Edward${i} King ${i}`,
        age: `${i}32`,
        address: `L${i}ondon, Park Lane no. ${i}`,
        D: i,
        E: `New${i}DEFG`,
        F: `New${i}FGHJ`,
        G: `New${i}QWER`
      })
    }
    setdataSource([...data])
    setcolumns([
      {
        title: '序号',
        dataIndex: 'index',
        key: 'index',
        render: (text: any, record: any, index: number) => `${index + 1}`,
        width: 80,
        align: 'center'
      },
      {
        title: 'Name',
        dataIndex: 'name',
        key: 'name',
        align: 'center'
      },
      {
        title: 'Age',
        dataIndex: 'age',
        key: 'age',
        align: 'center'
      },
      {
        title: 'Address',
        dataIndex: 'address',
        key: 'address',
        align: 'center'
      },
      {
        title: 'D',
        dataIndex: 'D',
        key: 'D',
        align: 'center'
      },
      {
        title: 'E',
        dataIndex: 'E',
        key: 'E',
        align: 'center'
      },
      {
        title: 'F',
        dataIndex: 'F',
        key: 'F',
        align: 'center'
      },
      {
        title: 'G',
        dataIndex: 'G',
        key: 'G',
        align: 'center'
      }
    ])
  }, [])
  return (
    <div id="ManagePage" className="ManagePage">
      {useMemo(() => {
        return <DynamicTable dataSource={dataSource} columns={columns} />
      }, [dataSource, columns])}
    </div>
  )
}

export default ManagePage

子组件DynamicTable 接收到值,并进行处理 

 

先给获取到的数据添加唯一标识(这里我是自定义的数据,所以传过来接收到就会有key)

 现在将接收到的值赋给sliceContent 

  const sliceContent = useMemo(() => {
    const sliceContentData =
      dataSource.length > 0
        ? dataSource.map((item, index) => ({
            ...item,
            key: `${index}`
          }))
        : []
    return sliceContentData
  }, [dataSource])

定义searchText和findTitle用来存储输入框输入的值和对应的key

 const [searchText, setSearchText] = useState<string>('') 
 const [findTitle, setFindTitle] = useState<string>('key') 

获取到数据中的key值,为每一个key值添加一个input输入框,然后添加到数据的最前面并且给input绑定change事件,传入两个值,一个是value,一个是key

  const inputOnChange = useCallback((e: React.ChangeEvent<HTMLInputElement>, s: string) => {
    setSearchText(e.target.value)
    setFindTitle(s)
  }, [])



 
  // 数据标题 -- 数据内容
  const dataKeys = useMemo(() => (sliceContent.length > 0 ? Object.keys(sliceContent[0]) : []), [sliceContent])

  // 定义过滤input
  const columnsInput = useMemo(() => {
    const inputColumns: any = {}

    for (let index = 0; index < dataKeys.length; index++) {
      // 将数据中的每一项赋值为input
      inputColumns[dataKeys[index]] = <Input key={dataKeys[index]} placeholder="" onChange={e => inputOnChange(e, dataKeys[index])} />
    }
    return inputColumns
  }, [dataKeys, inputOnChange])

定义完过滤框,就要将过滤框放在数据首行,这里不区分大小写 因为全部转化了

  // 数据
  const filteredData = useMemo(() => {
    if (sliceContent.length === 0) return []
    // 将数据进行处理 全部转换为string类型并且都是小写 需要区分大小写就去掉  .toLowerCase()
    const filtered = sliceContent.filter(item =>
      String(item[findTitle as keyof typeof item])
        .toLowerCase()
        .includes(searchText.toLowerCase())
    )

    // 数据的开头填入input搜索框
    filtered.unshift(columnsInput)

    // 将数据抛出
    return filtered
  }, [sliceContent, findTitle, searchText, columnsInput])

然后将表格中的数据改成filteredData就可以了,最后可以根据自己项目需求添加其他功能

完整代码:

import { Input, Table } from 'antd'
import { useCallback, useMemo, useState } from 'react'

const DynamicTable = (props: { dataSource: Array<any>; columns: Array<any> }) => {
  const { dataSource, columns } = props
  console.log('dataSource', dataSource, 'columns', columns)
  // 添加key属性 string类型
  const sliceContent = useMemo(() => {
    const sliceContentData =
      dataSource.length > 0
        ? dataSource.map((item, index) => ({
            ...item,
            key: `${index}`
          }))
        : []
    return sliceContentData
  }, [dataSource])

  const [searchText, setSearchText] = useState<string>('') // 输入框改变事件 内容
  const [findTitle, setFindTitle] = useState<string>('key') // 输入框改变事件 标题


  // 输入框change事件
  const inputOnChange = useCallback((e: React.ChangeEvent<HTMLInputElement>, s: string) => {
    setSearchText(e.target.value)
    setFindTitle(s)
  }, [])

  // 数据标题 -- 数据内容
  const dataKeys = useMemo(() =>  (sliceContent.length > 0 ? Object.keys(sliceContent[0]) : []), [sliceContent])

  // 定义过滤input
  const columnsInput = useMemo(() => {
    const inputColumns: any = {}

    for (let index = 0; index < dataKeys.length; index++) {
      // 将数据中的每一项赋值为input
      inputColumns[dataKeys[index]] = <Input key={dataKeys[index]} placeholder="" onChange={e => inputOnChange(e, dataKeys[index])} />
    }
    return inputColumns
  }, [dataKeys, inputOnChange])

  // 数据
  const filteredData = useMemo(() => {
    if (sliceContent.length === 0) return []
    // 将数据进行处理 全部转换为string类型并且都是小写 需要区分大小写就去掉  .toLowerCase()
    const filtered = sliceContent.filter(item =>
      String(item[findTitle as keyof typeof item])
        .toLowerCase()
        .includes(searchText.toLowerCase())
    )

    // 数据的开头填入input搜索框
    filtered.unshift(columnsInput)

    // 将数据抛出
    return filtered
  }, [sliceContent, findTitle, searchText, columnsInput])

  return (
    <Table
      className="DynamicTable"
      dataSource={filteredData}
      bordered={true}
      tableLayout={'fixed'}
      columns={columns}
      pagination={{
        total: filteredData.length,
        showTotal: total => `共 ${total} 条`,
        showSizeChanger: true,
        showQuickJumper: true,
        pageSizeOptions: [10, 50, 100, 1000]
      }}
    />
  )
}

export default DynamicTable

上面代码只适合一次搜索,不支持多条件同时搜索

版本2.0

没有进行大更改,就只是改了一下搜索条件,原本是String字符串,改成了数组然后循环查找就好了

修改地方:

1.删除这两行代码

  const [searchText, setSearchText] = useState<string>('') // 输入框改变事件 内容
  const [findTitle, setFindTitle] = useState<string>('key') // 输入框改变事件 标题

用下面这一个取而代之 

  const [searchText, setSearchText] = useState<string[]>([])

2.输入框事件

  // 输入框change事件
  const inputOnChange = useCallback((e: React.ChangeEvent<HTMLInputElement>, s: string) => {
    setSearchText(e.target.value)
    setFindTitle(s)
  }, [])

修改为

  const inputOnChange = useCallback(
    (e: React.ChangeEvent<HTMLInputElement>, s: string) => {
      const newSearchText = [...searchText]
      newSearchText[dataKeys.indexOf(s)] = e.target.value
      setSearchText(newSearchText)
    },
    [dataKeys, searchText]
  )

3.过滤数据方法

 // 数据
  const filteredData = useMemo(() => {
    // 将数据进行处理 全部转换为string类型并且都是小写 需要区分大小写就去掉  .toLowerCase()
    const filtered = sliceContent.filter(item =>
      String(item[findTitle as keyof typeof item])
        .toLowerCase()
        .includes(searchText.toLowerCase())
    )

    // 数据的开头填入input搜索框
    filtered.unshift(columnsInput)

    // 将数据抛出
    return filtered
  }, [sliceContent, findTitle, searchText, columnsInput])

修改为

  // 数据
  const filteredData = useMemo(() => {
    if (sliceContent.length === 0) return []
    const filtered = sliceContent.filter(item => {
      for (let i = 0; i < dataKeys.length; i++) {
        const key = dataKeys[i]
        const searchValue = searchText[i] || ''
        if (!String(item[key]).toLowerCase().includes(searchValue.toLowerCase())) {
          return false
        }
      }
      return true
    })
    filtered.unshift(columnsInput)
    return filtered
  }, [sliceContent, searchText, dataKeys, columnsInput])

完整代码:

import { Input, Table } from 'antd'
import { useCallback, useMemo, useState } from 'react'

const DynamicTable = (props: { dataSource: Array<any>; columns: Array<any> }) => {
  const { dataSource, columns } = props

  // 添加key属性 string类型
  const sliceContent = useMemo(() => {
    const sliceContentData =
      dataSource.length > 0
        ? dataSource.map((item, index) => ({
            ...item,
            key: `${index}`
          }))
        : []
    return sliceContentData
  }, [dataSource])

  const [searchText, setSearchText] = useState<string[]>([])

  // 数据标题 -- 数据内容
  const dataKeys = useMemo(() => (sliceContent.length > 0 ? Object.keys(sliceContent[0]) : []), [sliceContent])

  const inputOnChange = useCallback(
    (e: React.ChangeEvent<HTMLInputElement>, s: string) => {
      const newSearchText = [...searchText]
      newSearchText[dataKeys.indexOf(s)] = e.target.value
      setSearchText(newSearchText)
    },
    [dataKeys, searchText]
  )

  // 定义过滤input
  const columnsInput = useMemo(() => {
    const inputColumns: any = {}
    for (let index = 0; index < dataKeys.length; index++) {
      // 将数据中的每一项赋值为input
      inputColumns[dataKeys[index]] = <Input  defaultValue={searchText[index]} key={dataKeys[index]} placeholder="" onChange={e => inputOnChange(e, dataKeys[index])} />
    }
    return inputColumns
  }, [dataKeys, inputOnChange])

  // 数据
  const filteredData = useMemo(() => {
    if (sliceContent.length === 0) return []
    const filtered = sliceContent.filter(item => {
      for (let i = 0; i < dataKeys.length; i++) {
        const key = dataKeys[i]
        const searchValue = searchText[i] || ''
        if (!String(item[key]).toLowerCase().includes(searchValue.toLowerCase())) {
          return false
        }
      }
      return true
    })
    filtered.unshift(columnsInput)
    return filtered
  }, [sliceContent, searchText, dataKeys, columnsInput])

  return (
    <Table
      className="DynamicTable"
      dataSource={filteredData}
      bordered={true}
      tableLayout={'fixed'}
      columns={columns}
      pagination={{
        total: filteredData.length,
        showTotal: total => `共 ${total} 条`,
        showSizeChanger: true,
        showQuickJumper: true,
        pageSizeOptions: [10, 50, 100, 1000]
      }}
    />
  )
}

export default DynamicTable

使用中有任何报错欢迎私信询问

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

猫和老许

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值