js树形选择组件Tree

js树形组件Tree

1. 使用方式

  • 配置信息

    // 容器位置
    pNode: 'body'
    // 每一个title的padding
    titlePadding: 18
    // 数据源
    /*
    [
      {
        label: '',
        children:[
          {
            label: '',
            children: []
          }
       }                                                        
    ]
    */
    data: []
    // 格式化显示的字符串
    labelFormat: item => item.label
    // 点击时触发
    /**
      * 点击时触发
      * @param item 当前点击的项
      * @param path 路劲的数组
      * @param e 当前点击事件
      */
    onClick: (item, path, e) => {}
    
  • 使用实例

    <template>
      <div class="home">
      </div>
    </template>
    
    <script>
    // @ is an alias to /src
    const { Tree, Message } = require('@/assets/js/util')
    
    export default {
      name: 'Home',
      data () {
        return {
          tree: [
            {
              id: '1',
              label: '这些年',
              children: [
                {
                  id: '1-1',
                  label: '一个人'
                }
              ]
            },
            {
              id: '2',
              label: '一个人',
              children: [
                {
                  id: '2-1',
                  label: '风也走',
                  children: [
                    {
                      id: '2-1-1',
                      label: '有过泪',
                      children: [
                        {
                          id: '2-1-1-1',
                          label: '还记得坚持什么'
                        },
                        {
                          id: '2-1-1-2',
                          label: '什么也记不得了'
                        }
                      ]
                    }
                  ]
                },
                {
                  id: '2-2',
                  label: '雨也过',
                  children: [
                    {
                      id: '2-2-1',
                      label: '真爱过'
                    }
                  ]
                },
                {
                  id: '2-3',
                  label: '才会懂'
                }
              ]
            },
            {
              id: '3',
              label: '有过痛'
            }
          ]
        }
      },
      mounted () {
        // eslint-disable-next-line no-new
        new Tree({
          data: this.tree,
          pNode: '.home',
          onClick (item, path, e) {
            if (!item.children) {
              console.log(path, e)
              Message.info(`您已选择:【${item.label}`)
            }
          }
        })
      },
      methods: {}
    }
    </script>
    
    
  • 演示效果

在这里插入图片描述

2. js代码

/*
树形控件
 */

const {
  getDom,
  createDom,
  cssFromObj
} = require('./Common')

class Tree {
  constructor (config) {
    this.config = {
      pNode: 'body',
      // 每一个title的padding
      titlePadding: 18,
      data: [],
      // 格式化显示的字符串
      labelFormat: item => item.label,
      // 点击时触发
      /**
       * 点击时触发
       * @param item 当前点击的项
       * @param path 路劲的数组
       * @param e 当前点击事件
       */
      onClick: (item, path, e) => {}
    }
    this.init(config)
    this.render()
  }

  init (config) {
    Object.assign(this.config, config)
    this.parent = getDom(this.config.pNode)
    if (!this.parent) {
      throw new Error('The progress component needs a parent node, you can define by setting the "pNode" property')
    }
    this.treeContainer = createDom('hxl-tree-box')
  }

  generateTree (data, num = 0, path = []) {
    const treeList = createDom('hxl-tree-list')
    data.forEach(li => {
      const treeItem = createDom('hxl-tree-item')
      const treeItemTitle = createDom('hxl-tree-title')
      treeItemTitle.style = cssFromObj({
        paddingLeft: `${this.config.titlePadding * num}px`
      })
      treeItemTitle.innerText = this.config.labelFormat(li)
      treeItem.appendChild(treeItemTitle)
      treeItemTitle.onclick = (e) => {
        if (e.target.classList.contains('sub-title')) {
          if (e.target.classList.contains('active')) {
            e.target.classList.remove('active')
            e.target.nextSibling.style.display = 'none'
          } else {
            e.target.classList.add('active')
            e.target.nextSibling.style.display = 'block'
          }
        }
        this.config.onClick(li, [...path, li], e)
      }
      if (li.children) {
        treeItem.classList.add('has-sub')
        treeItemTitle.classList.add('sub-title')
        // 创建子tree
        const subTree = createDom('hxl-tree-sub-item')
        subTree.appendChild(this.generateTree(li.children, num + 1, [...path, li]))
        treeItem.appendChild(subTree)
      }
      treeList.appendChild(treeItem)
    })
    return treeList
  }

  render () {
    this.treeList = this.generateTree(this.config.data)
    this.treeContainer.appendChild(this.treeList)
    this.parent.appendChild(this.treeContainer)
  }

  set data (data) {
    if (Array.isArray(data)) {
      this.config.data = data
    } else {
      throw new Error('data property must be an Array')
    }
  }

  get data () {
    return this.config.data
  }
}

module.exports = {
  Tree
}

css样式

.hxl-tree-box {
  width: 100%;
  padding-left: 10px;
}
.hxl-tree-item {
  cursor: pointer;

  &.has-sub {
    .hxl-tree-title {
      -webkit-user-select: none;
      -moz-user-select: none;
      -ms-user-select: none;
      user-select: none;
      display: flex;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
      align-items: center;
      &.sub-title.active {
        &:before {
          transform: rotate(90deg);
        }
      }
    }
    &>.hxl-tree-title.sub-title:before {
      content: '';
      width: 0;
      height: 0;
      display: inline-block;
      justify-content: center;
      margin-right: 5px;
      border-left: 6px solid #afafaf;
      border-top: 4px solid transparent;
      border-bottom: 4px solid transparent;
    }
  }
  .hxl-tree-title {
    &:hover {
      background: #f5f7fa;
    }
  }
  .hxl-tree-sub-item {
    display: none;
    transition: all 2s;
  }
}

这么简单好用,还不快快用起来吗,实际使用中可根据自己的需要进行修改,有任何疑问也可以一起讨论,当然若是您有其他不同的见解与优化,也希望能够提出来,大家多多交流,互相促进~~

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值