简易树形选择组件——初始版全部代码

简易树形选择组件——初始版全部代码

ArrowTree
interface StoreValue {
  data: any;
  setArrowTreeData: (data: any) => void
}
const defaultData = {
  children:[
    {
      "title":"组织1",
      "key": "0-1",
      "children":[
        {
          "title":"部门1",
          "key":"0-1-1",
          "children": [
            {
              title: '2018年9月10号校招啦啦啦',
              key : '0-1-1-0',
              checked: false,
              children: [],
              "parentKey": "0-1-1"
            }
          ],
          "collapsed": true,
          "checked": false,
          "parentKey": '0-1'
        },
        {
          "title":"部门1.5",
          "key":"0-1-2",
          "children": [
            {
              title: '2018年9月10号校招啦啦啦',
              key : '0-1-2-0',
              checked: false,
              children: [],
              "parentKey": "0-1-1"
            }
          ],
          "collapsed": true,
          "checked": false,
          "parentKey": '0-1'
        },
      ],
      "collapsed": true,
      "checked": true,
      "parentKey": 'root'
    },
    {
      "title":"组织2",
      "key": "0-2",
      "children":[
        {
          "title":"部门2",
          "key":"0-2-1",
          "children": [
            {
              title: '2018年和外和发发和发挥',
              key : '0-2-1-0',
              checked: false,
              children: [],
              "parentKey": "0-2-1"
            }
          ],
          "collapsed": true,
          "checked": false,
          "parentKey": '0-2'
        },
      ],
      "collapsed": true,
      "checked": true,
      "parentKey": 'root'
    }
  ],
  key: "root"
}
const Store = React.createContext({} as StoreValue)
const ArrowTree = (props:any):JSX.Element => {
  const [data,setData] = useState(defaultData)
  const setArrowTreeData = (newData: any) => {
    setData(newData)
  }
  const TreeArr = data.children.map((item: any,index: number) => {
    return (
      <div className="arrow-tree" key={item.key}>
          <TreeNode paddingLeft={35} positionLeft={20} keyArr={[item.key]} {...item}/>
      </div>
    )
  })
  return (
    <div>
      <Store.Provider value={{data,setArrowTreeData}}>
        {TreeArr}
      </Store.Provider>
    </div>
  )
}
TreeNode
// 递归处理子组件的checked 
const DealRecursionChild = (dealData: any,checked: boolean) => {
  if(dealData.children && dealData.children.length!==0) {
    dealData.children.forEach((item:any) => {
      item.checked = checked
      if(item.children && item.children.length!==0) {
        DealRecursionChild(item,checked)
      }
    })
  }
}
// 处理父组件的checked
const DealParent = (dealParentArr: any[],checked: boolean) => {
  // 遍历处理其父节点选中不选中的问题
  for(let i=dealParentArr.length-2;i>=0;i--) {
    let childCount = 0
    dealParentArr[i].children.forEach((item: any) => {
      if(item.checked === true) {
        childCount ++
      }
    })
    if(childCount === dealParentArr[i].children.length) {
      dealParentArr[i].checked = true
    }else {
      dealParentArr[i].checked = false
    }
  }
}

const TreeNode = (props: any) => {
  const {data,setArrowTreeData} = useContext(Store)
  const {paddingLeft,positionLeft,collapsed,children,keyArr,title,checked} = props
  const handleCollapsed = () => {
    // 操作原始的data
    const newData = JSON.parse(JSON.stringify(data))
    let dealData = newData
    keyArr.forEach((key: string) => {
      dealData = dealData.children.find((item: any) => item.key === key)
    })
    dealData.collapsed = !dealData.collapsed
    setArrowTreeData(newData)
  }
  const handleChecked = (e: React.ChangeEvent) => {
    // 操作原始的data
    e.stopPropagation()
    const newData = {...data}
    let dealData = newData
    // 记录其父节点的问题
    let dealParentArr: any[] = []
    keyArr.forEach((key: string) => {
      dealData = dealData.children.find((item: any) => item.key === key)
      dealParentArr.push(dealData)
    })
    // 不受控 如果受控的话
    let checked = !dealData.checked
    dealData.checked = checked
    // 遍历处理其子节点选中不选中的问题
    DealRecursionChild(dealData,checked)
    // 遍历处理其父节点选中不选中的问题
    DealParent(dealParentArr,checked)
    setArrowTreeData(newData)
  }
  const mapTreeData = (children: any[],paddingLeft: number) => {
    const newChildren = children.map(item => {
      const newKeyArr = [...keyArr,item.key]
      return <TreeNode paddingLeft={paddingLeft+15} positionLeft={paddingLeft} keyArr={newKeyArr} {...item}/>
    })
    return newChildren
  }
  return (
    <>
      <div className="show" onClick={handleCollapsed} style={{paddingLeft: paddingLeft+'px'}}>
        <div>
          { children.length!==0 ?(<strong className={`${collapsed?'':'arrow-down' } arrow-icon`} style={{left: positionLeft-17+'px'}}>
            <Icon/>
          </strong>):null}
          <div className='checkbox' style={{left:positionLeft+'px'}}>
            <input type="checkbox"  onChange={handleChecked} checked={checked}/>
          </div>
          <div>{title}</div>
        </div>
      </div>
      <div className="children">
        {
          (!collapsed && Array.isArray(children) && children.length !==0) ? 
          mapTreeData(children,paddingLeft) : null
        }
      </div>
    </>
  )
}

export default ArrowTree
index.css
.arrow-tree {
  width: 240px;
  line-height: 30px;
}
.arrow-tree .show {
  cursor: pointer;
}
.arrow-tree .show {
  position: relative;
  width: 100%;
  box-sizing: border-box;
  color: #111;
  font-size: 14px;
}
.arrow-tree .show .checkbox {
  position: absolute;
  left: 20px;
  top: 1px;
}

.arrow-tree .show .checkbox+div {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.arrow-tree .show .arrow-icon {
  position: absolute;
}
.arrow-tree .show .arrow-down {
  transform: rotate(90deg);
}
.arrow-tree .show:hover {
  background-color: skyblue;
}
.arrow-tree .children {
  box-sizing: border-box;
}
Icon
import React from 'react'

const Icon = ():JSX.Element => {
  return (
    <svg width="12px" height="12px" viewBox="0 0 18 18" color="#83898F"><g fill="none" fillRule="evenodd"><path d="M0 0h18v18H0z"></path><path d="M5 2.944c0-1.032.297-1.467 2.014 0l5.57 5.13a1.24 1.24 0 0 1 0 1.855l-5.57 5.13c-1.697 1.594-2.014.864-2.014 0V2.943z" fill="#83898F"></path></g></svg>
  )
}

export default Icon
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值