手把手教学~基于element封装tree树状下拉框

在日常项目开发中,树状下拉框的需求还是比较常见的,但是element并没有这种组件以供使用。在这里,小编就基于element如何封装一个树状下拉框做个详细的介绍。

通过这篇文章,你可以了解学习到一个树状下拉框组件是如何一步一步封装成功的。

话不多说,先看效果图:

手把手教学~基于element封装tree树状下拉框_第1张图片

封装组件

该组件主要基于element的select组件、tree组件及input组件进行二次封装的。

组件布局

首先我们需要基于这几个组件对我们的组件进行布局,话不多说直接上代码:




  .el-scrollbar .el-scrollbar__view .el-select-dropdown__item{
    height: auto;
    max-height: 274px;
    padding: 0;
    overflow: hidden;
    overflow-y: auto;
  }
  .el-select-dropdown__item.selected{
    font-weight: normal;
  }
  ul li >>>.el-tree .el-tree-node__content{
    height:auto;
    padding: 0 20px;
  }
  .el-tree-node__label{
    font-weight: normal;
  }
  .el-tree >>>.is-current .el-tree-node__label{
    color: #409EFF;
    font-weight: 700;
  }
  .el-tree >>>.is-current .el-tree-node__children .el-tree-node__label{
    color:#606266;
    font-weight: normal;
  }


注:css添加scoped属性,是为了让css只在该组件生效,避免样式污染

这个时候直接使用肯定是会报错的,因为我们组件该传的参数还未传递。

组件数据完善

上面我们已经完成了布局,接下来就是为其丰富数据了,因为我们这个组件肯定是复用的,因此我们设计数据的时候,需要把常用的数据属性提取出来通过props传递接收。我提取的主要有几下几个数据:

props:{
    /* 配置项 */
    props:{
      type: Object,
      default:()=>{
        return {
          value:'id',             // ID字段名
          label: 'title',         // 显示名称
          children: 'children'    // 子级字段名
        }
      }
    },
    /* 选项列表数据(树形结构的对象数组) */
    options:{
      type: Array,       
      default: ()=>{ return [] }
    },
    /* 初始值 */
    value:{
      default: ()=>{ return null }
    },
    /* 可清空选项 */
    clearable:{
      type:Boolean,
      default:()=>{ return true }
    },
    /* 自动收起 */
    accordion:{
      type:Boolean,
      default:()=>{ return false }
    },
    placeholder:{
      type:String,
      default:()=>{return "请选择"}
    }
  },

大家可能注意到,我所有prop字段都给了type属性,唯独value没有,这是因为在实际使用中下拉框的数据value值可能是字符串(String)也可能是数字(Number),为了项目开发中控制台不报太多无意义的错,此处就没有规定其type。

接收到prop之后,我们就开始对组件进行数据的处理,直接上代码:



当数据过多的时候,滚动条会出现两条,如下所示:

手把手教学~基于element封装tree树状下拉框_第2张图片

处理方法如下:

// 初始化滚动条
initScroll(){
  this.$nextTick(()=>{
    let scrollWrap = document.querySelectorAll('.el-scrollbar .el-select-dropdown__wrap')[0]
    let scrollBar = document.querySelectorAll('.el-scrollbar .el-scrollbar__bar')
    scrollWrap.style.cssText = 'margin: 0px; max-height: none; overflow: hidden;'
    scrollBar.forEach(ele => ele.style.width = 0)
  })
},

mounted中调用该方法就可以了,效果如下:

手把手教学~基于element封装tree树状下拉框_第3张图片

点击选中

数据也渲染显示出来了,这个时候我们需要实现点击数据选中功能。

思路很简单:

  • select组件绑定value值

  • tree组件绑定节点点击事件

  • 点击事件中获取value和label

  • 将获取的值赋给select组件以及返回给父组件

代码如下:


data() {
    return {
      valueId:this.value,// 初始值
      valueTitle:'',
      defaultExpandedKey:[]
    }
},
// 切换选项
handleNodeClick(node){
  this.valueTitle = node[this.props.label]//获取label
  this.valueId = node[this.props.value]//获取value
  this.$emit('getValue',this.valueId)//传值给父组件
},

这样点击选中功能就实现了,但是有个问题,点击之后,下拉框选项没有隐藏,我们只需要再调用一下select组件的blur方法即可实现隐藏

数据初始化

细心的小伙伴肯定已经发现了,上面有一个初始值,并且在选择器中,初始数据也是必不可少的。实现思路如下:

  • watch监听prop中value数据变化

  • 将初始值做对应赋值

  • 获取初始值对应的label并做对应赋值

  • 设置tree组件的默认选中状态

  • 设置tree组件的默认展开节点

代码如下:

watch: {
    value(){
      this.valueId = this.value
      this.initHandle()
    }
},
// 初始化值
initHandle(){
  if(this.valueId){
    // 初始化显示label
    this.valueTitle = this.$refs.selectTree.getNode(this.valueId).data[this.props.label]     
    this.$refs.selectTree.setCurrentKey(this.valueId)// 设置默认选中
    this.defaultExpandedKey = [this.valueId]// 设置默认展开
  } 
},

mounted中调用执行既可

清除选中

一般输入框或者选择器都有清除功能,我们的组件自然也少不了清除功能,实现思路如下:

  • 给select组件设置clearable属性

  • 给select组件添加清除监听事件

  • 在监听事件中清除tree组件选中,并清除父组件中的值

代码如下:



// 清除选中
clearHandle(){
  this.valueTitle = ''
  this.valueId = null
  this.defaultExpandedKey = []
  this.clearSelected()
  this.$emit('getValue',null)
},
/* 清空选中样式 */
clearSelected(){
  let allNode = document.querySelectorAll('#tree-option .el-tree-node')
  allNode.forEach((element)=>element.classList.remove('is-current'))
},

筛选数据

当tree中数据量过大时,我们需要筛选数据,实现思路如下:

  • 给tree组件添加filter-node-method方法

  • 添加一个输入框,输入筛选的内容

  • 监听输入内容变化,并调用tree组件的筛选方法

代码如下:



.selectInput{
    padding: 0 5px;
    box-sizing: border-box;
}
filterNode(value, data) {
  if (!value) return true;
  return data.name.indexOf(value) !== -1;
}
watch: {
    filterText(val) {
      this.$refs.selectTree.filter(val);
    }
},

这样一个简单的树状下拉框组件就封装好了。

使用组件

下面给个简单的使用示例:


 

历史好文推荐:

1、Vue3之——和Vite不得不说的事                        

2、大厂面试算法之斐波那契数列                        

3、2020字节跳动面试题一面解析                          

关注公众号【前端优选】,助力成为高级前端架构!


添加个人微信,进群与小伙伴一起玩耍~“在看转发”是最大的支持

你可能感兴趣的:(js,vue,css,html,react)