react 条件分支组件

2021-12-08 10:10:21 浏览数 (2)

通过组件模拟条件分支

例子

代码语言:javascript复制
      <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

代码语言:javascript复制
<If status={status}>
   ....
</If>
<If status={status}>
   ....
</If>

if else

代码语言:javascript复制
<Branch>
    <If status={status}>
        ...
    </If>
    <Else>
        ...
    </Else>
</Branch

if else-if

代码语言:javascript复制
<Branch>
    <If status={status01}>
        ...
    </If>
    <ElseIf status={status02}>
        ...
    </ElseIf>
</Branch

if else-if else

代码语言:javascript复制
<Branch>
    <If status={status01}>
        ...
    </If>
    <ElseIf status={status02}>
        ...
    </ElseIf>
    <Else>
        ...
    </Else>
</Branch

组件实现

If

代码语言:javascript复制
export const If = props => {
  const {
    children,
    status
  } = props

  return (
    <>
    { status ? children : null }
    </>
  )
}

ElseIf

代码语言:javascript复制
export const ElseIf = props => {
  return (
    <>
     { props.status ? props.children : null }
    </>
  )
}

Else

代码语言:javascript复制
export const Else = props => {
  return (
    <>
      { props.children }
    </>
  )
}

Branch

代码语言:javascript复制
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}
    </>
  )
}

0 人点赞