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

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

相关推荐
mldong7 小时前
你的 Vue3 项目也能有钉钉同款审批流设计器:npm 装包,10 分钟画出第一条审批流
前端·vue.js
2分钟速写快排7 小时前
什么是 RAG?如何用 RAG 实现一个用户记忆?
前端·后端·ai编程
passerby60618 小时前
如何自己造一个时间处理库
前端·javascript·github
走到天涯海角9 小时前
react里面的长列表渲染优化
前端·react.js·前端框架
小羊没烦恼!9 小时前
Hello Web API系列教程——Web API与国际化
java·服务器·前端·javascript·php
北岛贰9 小时前
迷茫焦虑期,我做了一个带支付带官网的 AI 聊天虚拟恋人 App
前端·人工智能·后端
mayaairi11 小时前
Vue2 组件通讯(三):全局事件总线、PubSub、插槽与组件实例属性
前端·javascript·vue.js
kyriewen11 小时前
面试官问我:AI 都能写代码了,前端凭什么还值 25K
前端·javascript·人工智能
风骏时光牛马12 小时前
AI源码分析:拆解模型底层实现逻辑
前端
IT_陈寒12 小时前
React子组件莫名其妙重渲染?你可能漏了这个Hook
前端·人工智能·后端