# react 简易折叠面板实现
# 前言:
折叠面板应该是日常开发中用的很多的一个效果,之前也没太接触过,看了下 antd 的折叠面板,但是感觉面板 header 部分可能有些简洁,如果想在头部多加一些东西的话,可能有些麻烦,于是乎就决定自己搞一个。
为了更加灵活的控制面板是否折叠,只考虑实现一个面板组件,其折叠状态的方法通过 props 进行传递。
# 思路:
每个面板折叠、展开的动画效果其实就是去控制 collapse-panel
的 height
变化,并通过 transform
展示动画,所以在一开始就需要记录下每个面板的原始高度,否则在折叠面板后,高度就变为 0 了,这时候计算出来的值也为 0,就无法还原为初始高度了。
那么怎么计算初始高度呢?react 提供了一个 useRef
可以获取到组件的实例,其 current
上的 scrollheight
就是对应的高度,我们可以在初始化的时候获取并记录它。
const collapsePanel = useRef(null); | |
const [collapseOriginalHeight,setCollapseOriginalHeight]=useState('auto'); | |
useEffect(()=>{ | |
setCollapseOriginalHeight(`${collapsePanel.current.scrollHeight}px`); | |
},[]); |
那么接下来根据折叠 ( collapse
) 来动态的改变对应面板的高度就可以了
const collapseStyle={ | |
height:collapse?'0px':`${collapseOriginalHeight}`, | |
} | |
const body=( | |
<div className={bodyClass} style={bodyStyle,collapseStyle} ref={collapsePanel}> | |
{children} | |
</div> | |
); |
最后加一个 transition
效果
.MyCollapsePanel { | |
&-body { | |
padding:0px; | |
transition: height 500ms; | |
overflow: hidden; | |
} | |
} |
# 代码
export default function MyCollapsePanel(props) { | |
const { | |
prefixCls = "MyCollapsePanel", | |
className, | |
extra, | |
children, | |
collapse=false, | |
bodyStyle={}, | |
bordered = false, | |
...others | |
} = props; | |
const collapsePanel = useRef(null); | |
const [collapseOriginalHeight,setCollapseOriginalHeight]=useState('auto'); | |
useEffect(()=>{ | |
setCollapseOriginalHeight(`${collapsePanel.current.scrollHeight}px`); | |
},[]); | |
const bodyClass=classNames({ | |
[`${prefixCls}-body`]:true, | |
}); | |
const collapseStyle={ | |
height:collapse?'0px':`${collapseOriginalHeight}`, | |
} | |
const body=( | |
<div className={bodyClass} style={bodyStyle,collapseStyle} ref={collapsePanel}> | |
{children} | |
</div> | |
); | |
return <div> | |
{body} | |
</div>; | |
} |
使用:
父组件通过控制 collapse
来显示或折叠面板
const [collapse, setCollapse] = useState(false); | |
const handleCollapse = () => { | |
setCollapse((value) => { | |
return !value; | |
}); | |
}; | |
<MyCollapsePanel collapse={collapse}> | |
<div>//...具体内容</div> | |
</MyCollapsePanel>; |
效果展示