react 条件分支组件
2021-10-07 本文已影响0人
copyLeft
通过组件模拟条件分支
例子
<Branch> // 分支容器
<If status={false}> // if
if
</If>
<ElseIf status={false}> // else if
else
</ElseIf>
<br />
// 支持嵌套
<Else> // else
<Branch>
<If status={false}>
next level if
</If>
<ElseIf status={true}>
next level else-if
</ElseIf>
</Branch>
</Else>
end // 组件之间的任意位置可插入其他内容, 都将被渲染
</Branch>
image.png
基础组件
-
<Branch>
判断容器: 当存在多条件判断时,判断组件需要包裹在该组件下 -
<If>
if 判读, 单条If组件可不使用 Branch 包裹 -
<ElseIf>
else if 判断 -
<Else>
else 判断
组件用例
独立使用If
<If status={status}>
....
</If>
<If status={status}>
....
</If>
if else
<Branch>
<If status={status}>
...
</If>
<Else>
...
</Else>
</Branch
if else-if
<Branch>
<If status={status01}>
...
</If>
<ElseIf status={status02}>
...
</ElseIf>
</Branch
if else-if else
<Branch>
<If status={status01}>
...
</If>
<ElseIf status={status02}>
...
</ElseIf>
<Else>
...
</Else>
</Branch
组件实现
If
export const If = props => {
const {
children,
status
} = props
return (
<>
{ status ? children : null }
</>
)
}
ElseIf
export const ElseIf = props => {
return (
<>
{ props.status ? props.children : null }
</>
)
}
Else
export const Else = props => {
return (
<>
{ props.children }
</>
)
}
Branch
export const Branch = props => {
// 通过函数name属性判断组件类型
const types = [
// Branch.name,
If.name,
ElseIf.name,
Else.name
]
const _c = []
const bingo = 'BINGO'
let currentType
/**
* 遍历子元素,根据组件分类判断是否加入渲染队列中
*/
React.Children.forEach(props.children, (item) => {
const itemType = item.type ? item.type.name : null
const tactics = [
// 非分支组件或元素
[
() => !itemType || !types.includes(itemType),
() => { _c.push(item) }
],
// 分支组件状态为true时,后续分支组件不再追加
[
() => currentType === bingo,
() => {}
],
[
// if 判断
() => itemType === If.name && !currentType,
() => {
if(item.props.status){
currentType = bingo
_c.push(item)
}else{
currentType = itemType
}
}
],
[
// else if 判断
() => itemType === ElseIf.name && currentType === If.name,
() => {
if(item.props.status){
currentType = bingo
_c.push(item)
}else{
currentType = itemType
}
}
],
[
// else 判断
() => itemType === Else.name && (currentType === If.name || currentType === ElseIf.name),
() => {
currentType = bingo
_c.push(item)
}
]
]
const _b = tactics.find(([check]) => check())
if(_b){
_b[1]()
}else{
throw new Error(`分支组件类型错误 ${item.type}: ${item}`)
}
})
return (
<>
{ _c}
</>
)
}