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

需求背景:使用折叠面板的形式展示数据,面板内部数据需要在打开时请求接口获取。

遇到问题:最开始使用Antd 的折叠面板组件,它对于数据直接渲染是没问题的,但是不好满足打开面板时再动态加载数据的需求,于是自己手写了一个。

效果展示(已脱敏):
在这里插入图片描述

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

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

/* 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:

.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让父组件调用子组件的方法。

核心代码:


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

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值