2019-10-14
描述
渲染一个 Tab 菜单及其视图组件。
- 定义一个
TabItem
组件,可以传递给Tab
且只接受props.children
中通过函数名称认证的TabItem
,其余节点需要进行移除 - 使用
React.useState()
hook 初始化bindIndex
状态变量的值为props.defaultIndex
- 使用
Array.prototype.map
将收集的节点渲染为tab-menu
和tab-view
- 当点击
tab-menu
中的<button>
时,将会执行定义为changeTab
的函数 changeTab
执行传递的回调onTabClick
并更新bindIndex
,这会导致重新渲染,通过他们的index
重新计算tab-view
中每一项的style
和className
,以及tab-menu
按钮
实现
.tab-menu > button {
cursor: pointer;
padding: 8px 16px;
border: 0;
border-bottom: 2px solid transparent;
background: none;
}
.tab-menu > button.focus {
border-bottom: 2px solid #007bef;
}
.tab-menu > button:hover {
border-bottom: 2px solid #007bef;
}
function TabItem(props) {
return <div {...props} />;
}
function Tabs(props) {
const [bindIndex, setBindIndex] = React.useState(props.defaultIndex);
const changeTab = newIndex => {
if (typeof props.onTabClick === 'function') props.onTabClick(newIndex);
setBindIndex(newIndex);
};
const items = props.children.filter(item => item.type.name === 'TabItem');
return (
<div className="wrapper">
<div className="tab-menu">
{items.map(({ props: { index, label } }) => (
<button onClick={() => changeTab(index)} className={bindIndex === index ? 'focus' : ''}>
{label}
</button>
))}
</div>
<div className="tab-view">
{items.map(({ props }) => (
<div
{...props}
className="tab-view_item"
key={props.index}
style={{ display: bindIndex === props.index ? 'block' : 'none' }}
/>
))}
</div>
</div>
);
}
使用
ReactDOM.render(
<Tabs defaultIndex="1" onTabClick={console.log}>
<TabItem label="A" index="1">
Lorem ipsum
</TabItem>
<TabItem label="B" index="2">
Dolor sit amet
</TabItem>
</Tabs>,
document.getElementById('root')
);
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于