2019-09-23
描述
渲染一个包含多个可折叠内容组件的手风琴菜单。
- 定义一个
AccordionItem
组件,并将其传递给Accordion
。除了在props.children
中函数名称标识为AccordionItem
的节点外移除其余不必要的节点 - 每一个
AccordionItem
组件都渲染一个<button>
,通过props.handleClick
回调和传递到组件中的内容props.children
来更新Accordion
。他们的展现通过props.isCollapsed
及对应的style
来确定 - 在
Accordion
组件中,使用React.useState()
hook 来初始化状态变量bindIndex
的默认值为props.defaultIndex
- 在过滤出的节点中使用
Array.prototype.map
来渲染每一个可折叠的元素 - 定义
changeItem
方法,在点击AccordionItem
中的<button>
时将会被执行。changeItem
执行传递的回调函数onItemClick
并更新bindIndex
为被点击元素的index
属性值
实现
function AccordionItem(props) { const style = { collapsed: { display: 'none' }, expanded: { display: 'block' }, buttonStyle: { display: 'block', width: '100%' } }; return ( <div> <button style={style.buttonStyle} onClick={() => props.handleClick()}> {props.label} </button> <div className="collapse-content" style={props.isCollapsed ? style.collapsed : style.expanded} aria-expanded={props.isCollapsed} > {props.children} </div> </div> ); } function Accordion(props) { const [bindIndex, setBindIndex] = React.useState(props.defaultIndex); const changeItem = itemIndex => { if (typeof props.onItemClick === 'function') props.onItemClick(itemIndex); if (itemIndex !== bindIndex) setBindIndex(itemIndex); }; const items = props.children.filter(item => item.type.name === 'AccordionItem'); return ( <div className="wrapper"> {items.map(({ props }) => ( <AccordionItem isCollapsed={bindIndex !== props.index} label={props.label} handleClick={() => changeItem(props.index)} children={props.children} /> ))} </div> ); }
使用
ReactDOM.render( <Accordion defaultIndex="1" onItemClick={console.log}> <AccordionItem label="A" index="1"> Lorem ipsum </AccordionItem> <AccordionItem label="B" index="2"> Dolor sit amet </AccordionItem> </Accordion>, document.getElementById('root') );
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于