antd 中 Select 与 Pagination 结合 SelectPagination

一、why?

有时候我们需要 Select 组件中数据比较大,可能需要分页的问题,由于 antd 中并没有直接提供 Select 分页功能,我们需要自己写。可能也有很多其他的方案,就是滚动到底部加载,其实这种还是没有分页来的直接,分页的效果与表格相似。

二、需要的组件

  • Select 组件
  • Pagination 组件

这里的 Select 有两种用法,一种是 option 的数组像的形式,一种是 Option 渲染组件的形式。

三、组件设计

  • Option 使用组件的 memo 进行缓存,避免重复渲染。
  • type 设计为两个主要组件服务,和外部的数据获取,当然也可以内部实现 ajax 请求在组件内部实现数据获取。
  • 使用 dropdownRender 渲染 Select 和 Pagination 两个部分。

四、手动实现

ts 复制代码
import { Select, Pagination } from "antd";
import { memo, useMemo, useState } from "react";

function OptionComImpl({ data }: any) {
  return (
    <div>
      {data.map((item: any, index: number) => {
        return <Select.Option value={item.value} key={index}>{item.label}</Select.Option>;
      })}
    </div>
  );
}

const OptionCom = memo(OptionComImpl);

type ISelectPaginationProps = {
  data: any[]
  currentPage: number
  selectStyles: React.CSSProperties
  paginationStyles: React.CSSProperties
  paginationProps: any
  selectPagniationProps: any
}

const _data = [
    { label: "选项 1", value: "1" },
    { label: "选项 2", value: "2" },
    { label: "选项 3", value: "3" },
    { label: "选项 4", value: "4" },
    { label: "选项 5", value: "5" },
    { label: "选项 6", value: "6" },
    { label: "选项 7", value: "7" },
    { label: "选项 8", value: "8" },
    { label: "选项 9", value: "9" },
    { label: "选项 10", value: "10" },
    { label: "选项 11", value: "11" },
    { label: "选项 12", value: "12" },
    { label: "选项 13", value: "13" },
    { label: "选项 14", value: "14" },
    { label: "选项 15", value: "15" },
    { label: "选项 16", value: "16" },
    { label: "选项 17", value: "17" },
    { label: "选项 18", value: "18" },
    { label: "选项 19", value: "19" },
    { label: "选项 20", value: "20" },
    { label: "选项 21", value: "21" },
    { label: "选项 22", value: "22" },
  ];


export default function SelectPagination({ data = _data, ...props }: ISelectPaginationProps) {
  const [currentPage, setCurrentPage] = useState( props.currentPage || 1); // 当前页码
  const [skip] = useState(10);
  
  const dataSource = useMemo(() => {
    return data.slice(
      skip * (currentPage - 1),
      data.length - currentPage * skip > 0 ? currentPage * skip : data.length
    );
  }, [currentPage, data, skip]);
  return (
    <div>
      <Select
        style={{
          width: 200,
          ...props.selectStyles,
        }}
        dropdownRender={(menu, ...args) => {
          return (
            <div>
              {menu}
              <div style={{ padding: '10px 0px'}}>
                <Pagination
                  total={data.length}
                  showSizeChanger
                  size="small"
                  pageSize={skip}
                  onChange={(page) => {
                    setCurrentPage(page);
                  }}
                  {...props.paginationProps}
                />
              </div>
            </div>
          );
        }}
        {...props.selectPagniationProps}
      >
        {dataSource.map((item) => {
          return <OptionCom key={item.value} data={data} />;
        })}
      </Select>
    </div>
  );
}

五、分析

核心要知晓的点就是 dropdownRender 属性,渲染额外的内容。其中 menu 属性是不好修改的。同时我们需要计算初始分页数据 dataSource 当然也可以根据自己的需求重新实现,所以使用组件式的分页渲染数据。使用 useMemo 计算并缓存计算结果。本示例只是一个简单的示例。

六、示例

🌹remix-antd-extra 示例仓库

🌹remix-antd-extra 部署

七、小结

Select 与 Pagination 组件是一个常用的功能,因为可能 Select 中需要存放的数据比较大,使用滚动的方式也有需要滚动很久,使用分页的方式更加的合理。本文主要讨论的其中一个通用的实现方式,希望能够帮助到大家。

相关推荐
阿伟来咯~11 分钟前
记录学习react的一些内容
javascript·学习·react.js
吕彬-前端16 分钟前
使用vite+react+ts+Ant Design开发后台管理项目(五)
前端·javascript·react.js
学前端的小朱18 分钟前
Redux的简介及其在React中的应用
前端·javascript·react.js·redux·store
许野平25 分钟前
Rust: 利用 chrono 库实现日期和字符串互相转换
开发语言·后端·rust·字符串·转换·日期·chrono
guai_guai_guai28 分钟前
uniapp
前端·javascript·vue.js·uni-app
也无晴也无风雨29 分钟前
在JS中, 0 == [0] 吗
开发语言·javascript
bysking1 小时前
【前端-组件】定义行分组的表格表单实现-bysking
前端·react.js
王哲晓2 小时前
第三十章 章节练习商品列表组件封装
前端·javascript·vue.js
fg_4112 小时前
无网络安装ionic和运行
前端·npm
理想不理想v2 小时前
‌Vue 3相比Vue 2的主要改进‌?
前端·javascript·vue.js·面试