【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:

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

相关推荐
hackeroink1 小时前
【2024版】最新推荐好用的XSS漏洞扫描利用工具_xss扫描工具
前端·xss
迷雾漫步者3 小时前
Flutter组件————FloatingActionButton
前端·flutter·dart
向前看-3 小时前
验证码机制
前端·后端
燃先生._.4 小时前
Day-03 Vue(生命周期、生命周期钩子八个函数、工程化开发和脚手架、组件化开发、根组件、局部注册和全局注册的步骤)
前端·javascript·vue.js
高山我梦口香糖5 小时前
[react]searchParams转普通对象
开发语言·前端·javascript
m0_748235245 小时前
前端实现获取后端返回的文件流并下载
前端·状态模式
m0_748240256 小时前
前端如何检测用户登录状态是否过期
前端
black^sugar6 小时前
纯前端实现更新检测
开发语言·前端·javascript
寻找沙漠的人7 小时前
前端知识补充—CSS
前端·css