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

相关推荐
F-2H1 小时前
C语言:指针4(常量指针和指针常量及动态内存分配)
java·linux·c语言·开发语言·前端·c++
gqkmiss2 小时前
Chrome 浏览器插件获取网页 iframe 中的 window 对象
前端·chrome·iframe·postmessage·chrome 插件
m0_748247554 小时前
Web 应用项目开发全流程解析与实战经验分享
开发语言·前端·php
刘大辉在路上4 小时前
突发!!!GitLab停止为中国大陆、港澳地区提供服务,60天内需迁移账号否则将被删除
git·后端·gitlab·版本管理·源代码管理
m0_748255025 小时前
前端常用算法集合
前端·算法
真的很上进5 小时前
如何借助 Babel+TS+ESLint 构建现代 JS 工程环境?
java·前端·javascript·css·react.js·vue·html
web130933203985 小时前
vue elementUI form组件动态添加el-form-item并且动态添加rules必填项校验方法
前端·vue.js·elementui
NiNg_1_2345 小时前
Echarts连接数据库,实时绘制图表详解
前端·数据库·echarts
如若1236 小时前
对文件内的文件名生成目录,方便查阅
java·前端·python
追逐时光者6 小时前
免费、简单、直观的数据库设计工具和 SQL 生成器
后端·mysql