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 中需要存放的数据比较大,使用滚动的方式也有需要滚动很久,使用分页的方式更加的合理。本文主要讨论的其中一个通用的实现方式,希望能够帮助到大家。

相关推荐
姚*鸿的博客5 分钟前
pinia在vue3中的使用
前端·javascript·vue.js
宇文仲竹24 分钟前
edge 插件 iframe 读取
前端·edge
Kika写代码27 分钟前
【基于轻量型架构的WEB开发】【章节作业】
前端·oracle·架构
苹果酱05671 小时前
一文读懂SpringCLoud
java·开发语言·spring boot·后端·中间件
掐指一算乀缺钱1 小时前
SpringBoot 数据库表结构文档生成
java·数据库·spring boot·后端·spring
天下无贼!2 小时前
2024年最新版Vue3学习笔记
前端·vue.js·笔记·学习·vue
Jiaberrr2 小时前
JS实现树形结构数据中特定节点及其子节点显示属性设置的技巧(可用于树形节点过滤筛选)
前端·javascript·tree·树形·过滤筛选
赵啸林2 小时前
npm发布插件超级简单版
前端·npm·node.js
我码玄黄2 小时前
THREE.js:网页上的3D世界构建者
开发语言·javascript·3d
罔闻_spider2 小时前
爬虫----webpack
前端·爬虫·webpack