如何在reactstrap表格的Collapse组件中添加可切换Chevron图标
Reactstrap表格行折叠+Chevron图标切换实现方案
下面分两种场景给出实现方式,包括带状态管理和完全不使用组件state的方案:
一、受控组件方案(使用State)
这种方式通过组件state管理每行的折叠状态,逻辑直观,便于扩展:
实现步骤
- 定义state存储每行的折叠状态(多行建议用对象/Map存储唯一标识对应的状态)
- 为Chevron图标绑定点击事件,切换对应行的状态
- 根据状态切换图标方向,同时控制Collapse组件的
isOpen属性
完整代码
import React, { useState } from 'react'; import { Table, Collapse } from 'reactstrap'; import { faChevronDown, faChevronUp } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; const CollapsibleTable = () => { const [collapseStates, setCollapseStates] = useState({ row1: false, row2: false, }); const toggleCollapse = (rowKey) => { setCollapseStates(prev => ({ ...prev, [rowKey]: !prev[rowKey] })); }; return ( <Table bordered> <thead> <tr> <th>序号</th> <th>内容</th> <th>操作</th> </tr> </thead> <tbody> {/* 第一行 */} <tr> <td>1</td> <td>可折叠行1</td> <td> <button onClick={() => toggleCollapse('row1')} style={{ border: 'none', background: 'transparent', cursor: 'pointer' }} > <FontAwesomeIcon icon={collapseStates.row1 ? faChevronUp : faChevronDown} /> </button> </td> </tr> <tr> <td colSpan="3"> <Collapse isOpen={collapseStates.row1}> <div style={{ padding: '1rem' }}>行1折叠内容</div> </Collapse> </td> </tr> {/* 第二行 */} <tr> <td>2</td> <td>可折叠行2</td> <td> <button onClick={() => toggleCollapse('row2')} style={{ border: 'none', background: 'transparent', cursor: 'pointer' }} > <FontAwesomeIcon icon={collapseStates.row2 ? faChevronUp : faChevronDown} /> </button> </td> </tr> <tr> <td colSpan="3"> <Collapse isOpen={collapseStates.row2}> <div style={{ padding: '1rem' }}>行2折叠内容</div> </Collapse> </td> </tr> </tbody> </Table> ); }; export default CollapsibleTable;
二、无组件State方案(UncontrolledCollapse)
可以利用Reactstrap的UncontrolledCollapse组件自动管理折叠状态,无需手动维护state,以下提供两种实现方式:
方式1:结合useRef跟踪状态
通过useRef存储折叠状态,避免组件state触发重渲染,依赖UncontrolledCollapse的onToggle事件更新状态:
import React, { useRef, useState } from 'react'; import { Table, UncontrolledCollapse } from 'reactstrap'; import { faChevronDown, faChevronUp } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; const UncontrolledCollapsibleTable = () => { const collapseRefs = useRef({ row1: false, row2: false }); // 空state用于触发组件重渲染(仅为更新图标显示,无业务逻辑) const [, setForceUpdate] = useState(false); const handleToggle = (rowKey, isOpen) => { collapseRefs.current[rowKey] = isOpen; }; return ( <Table bordered> <thead> <tr> <th>序号</th> <th>内容</th> <th>操作</th> </tr> </thead> <tbody> <tr> <td>1</td> <td>无状态折叠行1</td> <td> <button id="toggle-row1" style={{ border: 'none', background: 'transparent', cursor: 'pointer' }} onClick={() => setForceUpdate(prev => !prev)} > <FontAwesomeIcon icon={collapseRefs.current.row1 ? faChevronUp : faChevronDown} /> </button> </td> </tr> <tr> <td colSpan="3"> <UncontrolledCollapse target="#toggle-row1" onToggle={(isOpen) => handleToggle('row1', isOpen)} > <div style={{ padding: '1rem' }}>行1无状态折叠内容</div> </UncontrolledCollapse> </td> </tr> <tr> <td>2</td> <td>无状态折叠行2</td> <td> <button id="toggle-row2" style={{ border: 'none', background: 'transparent', cursor: 'pointer' }} onClick={() => setForceUpdate(prev => !prev)} > <FontAwesomeIcon icon={collapseRefs.current.row2 ? faChevronUp : faChevronDown} /> </button> </td> </tr> <tr> <td colSpan="3"> <UncontrolledCollapse target="#toggle-row2" onToggle={(isOpen) => handleToggle('row2', isOpen)} > <div style={{ padding: '1rem' }}>行2无状态折叠内容</div> </UncontrolledCollapse> </td> </tr> </tbody> </Table> ); }; export default UncontrolledCollapsibleTable;
方式2:纯CSS控制图标(完全无JS状态)
利用UncontrolledCollapse展开时添加的show类,通过CSS选择器切换图标显示,完全不需要JS状态管理:
JSX代码
import React from 'react'; import { Table, UncontrolledCollapse } from 'reactstrap'; import { faChevronDown, faChevronUp } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import './CollapsibleTable.css'; const PureCSSCollapsibleTable = () => { return ( <Table bordered> <thead> <tr> <th>序号</th> <th>内容</th> <th>操作</th> </tr> </thead> <tbody> <tr className="collapsible-row"> <td>1</td> <td>纯CSS控制折叠行1</td> <td> <button id="toggle-row1" className="toggle-btn" style={{ border: 'none', background: 'transparent', cursor: 'pointer' }} > <FontAwesomeIcon icon={faChevronDown} className="icon-down" /> <FontAwesomeIcon icon={faChevronUp} className="icon-up" /> </button> </td> </tr> <tr> <td colSpan="3"> <UncontrolledCollapse target="#toggle-row1" className="collapse-content"> <div style={{ padding: '1rem' }}>纯CSS控制的折叠内容</div> </UncontrolledCollapse> </td> </tr> <tr className="collapsible-row"> <td>2</td> <td>纯CSS控制折叠行2</td> <td> <button id="toggle-row2" className="toggle-btn" style={{ border: 'none', background: 'transparent', cursor: 'pointer' }} > <FontAwesomeIcon icon={faChevronDown} className="icon-down" /> <FontAwesomeIcon icon={faChevronUp} className="icon-up" /> </button> </td> </tr> <tr> <td colSpan="3"> <UncontrolledCollapse target="#toggle-row2" className="collapse-content"> <div style={{ padding: '1rem' }}>纯CSS控制的折叠内容</div> </UncontrolledCollapse> </td> </tr> </tbody> </Table> ); }; export default PureCSSCollapsibleTable;
CSS代码(CollapsibleTable.css)
/* 默认显示向下图标 */ .toggle-btn .icon-up { display: none; } .toggle-btn .icon-down { display: inline-block; } /* 当折叠内容展开时,切换为向上图标(使用:has选择器,需现代浏览器支持) */ .collapsible-row:has(+ tr .collapse-content.show) .toggle-btn .icon-up { display: inline-block; } .collapsible-row:has(+ tr .collapse-content.show) .toggle-btn .icon-down { display: none; }
内容的提问来源于stack exchange,提问作者erondem
相关产品推荐
相关产品推荐

