【React 】折叠面板,点击展开时再请求数据

需求背景:使用折叠面板的形式展示数据,面板内部数据需要在打开时请求接口获取。
遇到问题:最开始使用Antd 的折叠面板组件,它对于数据直接渲染是没问题的,但是不好满足打开面板时再动态加载数据的需求,于是自己手写了一个。

效果展示(已脱敏):

话不多说,以下是手写的组件代码:

面板的header 内容结构可以根据自己需要调整

javascript 复制代码
/* eslint-disable @typescript-eslint/no-unused-vars */
import { DownOutlined, RightOutlined } from '@ant-design/icons';
import { Col, Row } from 'antd';
import { useRef, useState } from 'react';
import './style.less';
// 内容
import TableList from './TableList';

/** ===================================
 * @names: 自定义折叠面板业务组件
 * @description:
 * @author:
 * @date: 2024-06-20
 *======================================*/

export default function CollapseList(props: any) {
  const [active, setActive] = useState(false);
  const tableRef = useRef<any>();
  return (
    <div className="collapse-item">
      <div className="collapse-item-header">
        <Row>
          <Col span={12}>
            <div>test</div>
          </Col>
          <Col span={8}>
            <div>2022-06-20</div>
          </Col>
          <div className="expand">
            {!active ? (
              <div
                className="expandIconCpe"
                onClick={() => {
                  setActive(!active);
                  // 点击展开时调用子组件加载数据的方法请求
                  tableRef.current?.handleGetData();
                }}
              >
                展开
                <RightOutlined />
              </div>
            ) : (
              <div
                className="expandIconCpe"
                onClick={() => {
                  setActive(!active);
                }}
              >
                收起
                <DownOutlined />
              </div>
            )}
          </div>
        </Row>
      </div>
      <div
        className={
          active ? 'collapse-item-content-active' : 'collapse-item-content-hide'
        }
      >
        {/* 面板内容,可以自定义,我这里是封装了一个表格组件 用ref绑定 */}
        <TableList ref={tableRef} />
      </div>
    </div>
  );
}

样式css:

css 复制代码
.collapse-item {
  border-bottom: 1px solid rgba(5, 5, 5, 6%);
  border-radius: unset;
	
  .collapse-item-header {
    position: relative;
    padding: 12px 16px;
    color: rgba(0, 0, 0, 88%);
    cursor: pointer;

    .expand {
      font-size: 12px;
      position: absolute;
      right: 16px;
    }

    .expandIconCpe {
      color: #0065ff !important;
    }
  }

  .collapse-item-content-hide {
    display: none;
  }

  .collapse-item-content-active {
    display: block;
    background-color: #fff;
  }

  .ant-table-tbody > tr:last-child > td {
    border-bottom: none;
  }
 .ant-row {
    flex-wrap: nowrap;
    word-break: break-all;
  }
}

面板内容组件中写接口请求,使用 forwardRef + useImperativeHandle让父组件调用子组件的方法。

核心代码:

javascript 复制代码
import { forwardRef, useImperativeHandle} from 'react';

interface TableRef {
  handleGetData: (params: any) => void;
}
const TableList = forwardRef<TableRef>((props, ref) => {

  // 子组件中
  useImperativeHandle(ref, () => ({
  // handleGetData是暴露给父组件的方法
  handleGetData: (params: any) => {
   // 这里可以自定义封装接口请求,然后渲染数据
   
   },
 }));
})

export default TableList;

Tips:

为了提高性能,不让每次点击展开都去发起请求,可以在请求成功一次结果后,设置一个标记,下次再点击展开时,判断如果已经标记请求成功过了,就不发起请求,展示上一次结果。

相关推荐
大圣编程4 小时前
Python中continue语句的用法是什么?
开发语言·前端·python
yuhaiqiang4 小时前
随手 vibecoding 的浏览器插件已经 6000 多次下载,聊聊他的产品设计
前端·后端·面试
之歆5 小时前
Vue商品详情与放大镜组件
前端·javascript·vue.js
再吃一根胡萝卜5 小时前
如何把小米 MiMo 接入 CodeBuddy,打造私有 Agent
前端
负责的蛋挞7 小时前
异步HttpModule的实现方式
java·服务器·前端
YFF菲菲兔8 小时前
其他 Hooks 解析
react.js
丹宇码农9 小时前
把 HLS 字幕玩出花:zwPlayer 如何让 M3U8 视频支持全文搜索、翻译与码率自适应
前端·javascript·音视频·hls·视频播放器
2501_943782359 小时前
【共创季稿事节】猜数字游戏:二分法思维与交互式反馈
前端·游戏·microsoft·harmonyos·鸿蒙·鸿蒙系统
GV191rLvq10 小时前
基于Socket实现的最简单的Web服务器【ASP.NET原理分析】
服务器·前端·asp.net