如何使用React-grid-layout实现网格反向折叠功能
实现反向顺序折叠的React网格布局
要实现初始1行3列的盒子(1-3),并按3→2→1的顺序反向折叠,我们可以通过React状态管理结合react-grid-layout的动态布局控制,配合延迟执行来实现顺序折叠效果。
核心实现思路
- 使用
useState维护当前布局状态和折叠状态 - 添加触发折叠的按钮,点击后依次延迟修改布局,让盒子按3→2→1的顺序隐藏
- 通过过渡动画让折叠过程更平滑,同时过滤不可见盒子调整网格布局
修改后的完整代码
<div id="root"></div> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-grid-layout/1.3.4/react-grid-layout.min.js"></script> <script type="text/babel"> const { ResponsiveReactGridLayout } = ReactGridLayout; const GridLayout = () => { // 初始布局:仅显示Box1、Box2、Box3,新增visible字段控制可见性 const [layout, setLayout] = React.useState([ { i: 'a', x: 0, y: 0, w: 1, h: 1, visible: true }, { i: 'b', x: 1, y: 0, w: 1, h: 1, visible: true }, { i: 'c', x: 2, y: 0, w: 1, h: 1, visible: true }, ]); const [isFolding, setIsFolding] = React.useState(false); // 触发反向折叠:按3→2→1顺序依次隐藏 const handleFold = () => { if (isFolding) return; setIsFolding(true); // 第一步:隐藏Box3(key=c) setTimeout(() => { setLayout(prev => prev.map(item => item.i === 'c' ? {...item, visible: false} : item )); }, 0); // 第二步:隐藏Box2(key=b),延迟500ms setTimeout(() => { setLayout(prev => prev.map(item => item.i === 'b' ? {...item, visible: false} : item )); }, 500); // 第三步:隐藏Box1(key=a),延迟1000ms setTimeout(() => { setLayout(prev => prev.map(item => item.i === 'a' ? {...item, visible: false} : item )); setIsFolding(false); }, 1000); }; // 重置布局到初始状态 const handleReset = () => { setLayout([ { i: 'a', x: 0, y: 0, w: 1, h: 1, visible: true }, { i: 'b', x: 1, y: 0, w: 1, h: 1, visible: true }, { i: 'c', x: 2, y: 0, w: 1, h: 1, visible: true }, ]); setIsFolding(false); }; return ( <div> <div style={{ marginBottom: '20px' }}> <button onClick={handleFold} disabled={isFolding}> {isFolding ? '折叠中...' : '触发反向折叠'} </button> <button onClick={handleReset} style={{ marginLeft: '10px' }}>重置布局</button> </div> <ResponsiveReactGridLayout className="layout" // 过滤掉不可见的盒子,自动调整网格布局 layouts={{ lg: layout.filter(item => item.visible) }} breakpoints={{ lg: 1200, md: 996, sm: 768, xs: 480, xxs: 0 }} cols={{ lg: 3, md: 3, sm: 2, xs: 1, xxs: 1 }} rowHeight={200} width={800} // 禁止拖拽和缩放,保持布局稳定 isDraggable={false} isResizable={false} > <div key="a" style={{ backgroundColor: '#FF5733', width: '100%', height: '100%', // 添加透明度过渡动画 transition: 'opacity 0.3s ease', opacity: layout.find(item => item.i === 'a').visible ? 1 : 0 }} >Box 1</div> <div key="b" style={{ backgroundColor: '#C70039', width: '100%', height: '100%', transition: 'opacity 0.3s ease', opacity: layout.find(item => item.i === 'b').visible ? 1 : 0 }} >Box 2</div> <div key="c" style={{ backgroundColor: '#900C3F', width: '100%', height: '100%', transition: 'opacity 0.3s ease', opacity: layout.find(item => item.i === 'c').visible ? 1 : 0 }} >Box 3</div> </ResponsiveReactGridLayout> </div> ); }; ReactDOM.render(<GridLayout />, document.getElementById('root')); </script>
关键细节说明
- 状态控制:通过
visible字段标记每个盒子的显示状态,isFolding防止重复触发折叠 - 顺序逻辑:利用
setTimeout设置不同延迟,严格按照3→2→1的顺序执行隐藏操作 - 平滑过渡:给盒子添加
opacity过渡动画,避免折叠过程生硬 - 布局自适应:过滤不可见盒子后,网格布局会自动调整剩余元素的位置
内容的提问来源于stack exchange,提问作者codeBox
相关产品推荐
相关产品推荐

