如何在accordion折叠面板中保持至少一个expansion panel始终展开?
实现思路
核心逻辑是记录当前展开的面板ID/索引,在用户触发展开/关闭操作时校验:如果当前操作是要关闭最后一个处于展开状态的面板,直接拦截该操作即可。
不同场景的实现示例
1. 原生JavaScript + HTML 实现
- 先给每个面板加自定义属性比如
data-panel-id,用变量expandedPanels存储当前展开的面板ID集合 - 给每个面板的头部加点击事件监听:
// 初始化默认展开第一个面板 let expandedPanels = new Set(['panel1']) document.querySelectorAll('.expansion-panel-header').forEach(header => { header.addEventListener('click', (e) => { const targetPanelId = e.currentTarget.parentElement.dataset.panelId const isCurrentExpanded = expandedPanels.has(targetPanelId) // 如果是要关闭当前唯一展开的面板,直接拦截 if (isCurrentExpanded && expandedPanels.size === 1) { return } // 正常切换展开/关闭状态 if (isCurrentExpanded) { expandedPanels.delete(targetPanelId) e.currentTarget.parentElement.classList.remove('expanded') } else { // 如果是手风琴模式(一次只展开一个),先清空集合再添加 // expandedPanels.clear() expandedPanels.add(targetPanelId) e.currentTarget.parentElement.classList.add('expanded') } }) })
2. Vue3 + Element Plus 实现
如果用Element Plus的el-collapse组件,直接利用before-close钩子拦截即可:
<template> <el-collapse v-model="activeName" :before-close="handleBeforeClose"> <el-collapse-item title="面板1" name="1"></el-collapse-item> <el-collapse-item title="面板2" name="2"></el-collapse-item> <el-collapse-item title="面板3" name="3"></el-collapse-item> </el-collapse> </template> <script setup> import { ref } from 'vue' // 初始化默认展开第一个面板 const activeName = ref(['1']) const handleBeforeClose = (closingName) => { // 如果当前要关闭的是唯一展开的面板,返回false阻止关闭 if (activeName.value.length === 1 && activeName.value[0] === closingName) { return false } return true } </script>
3. React + Ant Design 实现
用Ant Design的Collapse组件,监听onChange事件,判断变更后的展开列表是否为空,为空就保持之前的展开状态:
import { useState } from 'react' import { Collapse } from 'antd' const items = [ { key: '1', label: '面板1', children: '内容1' }, { key: '2', label: '面板2', children: '内容2' }, { key: '3', label: '面板3', children: '内容3' }, ] export default function App() { const [activeKey, setActiveKey] = useState(['1']) const handleChange = (newActiveKey) => { // 如果新的展开列表为空,不更新状态 if (newActiveKey.length === 0) return setActiveKey(newActiveKey) } return <Collapse activeKey={activeKey} onChange={handleChange} items={items} /> }
注意事项
- 初始化的时候一定要默认展开至少一个面板,避免初始状态就全关
- 如果是手风琴模式(一次只能展开一个),逻辑可以更简化:禁止点击当前已经展开的面板的关闭操作即可
内容的提问来源于stack exchange,提问作者code
相关产品推荐
相关产品推荐

