.net bootstrap 下拉树状选择框_基于element封装tree树状下拉框

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

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

话不多说,先看效果图:

c6321460c8a9e2b1ec0106cdff7f393d.gif

封装组件

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

组件布局

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

"select">"options">"tree-option"
        ref="selectTree"
      >



注: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之后,我们就开始对组件进行数据的处理,直接上代码:

"placeholder" ref="select">"options">"tree-option"
        ref="selectTree"
        :accordion="accordion"
        :data="options"
        :props="props"
        :node-key="props.value"
        :default-expanded-keys="[]"
      >

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

912ae6e75dc1e1ac0b090ef4c104a4c8.png

处理方法如下:

// 初始化滚动条
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中调用该方法就可以了,效果如下:

7f81b0e6eb0dd978524c848a4958a3a3.png

点击选中

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

思路很简单:

  • select组件绑定value值
  • tree组件绑定节点点击事件
  • 点击事件中获取value和label
  • 将获取的值赋给select组件以及返回给父组件

代码如下:

"valueTitle" :placeholder="placeholder" ref="select">"valueTitle" :label="valueTitle" class="options">"tree-option"
        ref="selectTree"
        :accordion="accordion"
        :data="options"
        :props="props"
        :node-key="props.value"
        :default-expanded-keys="defaultExpandedKey"
        @node-click="handleNodeClick"
        >
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组件选中,并清除父组件中的值

代码如下:

"valueTitle" :clearable="clearable" @clear="clearHandle" :placeholder="placeholder" ref="select">
// 清除选中
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组件的筛选方法

代码如下:

"valueTitle" :clearable="clearable" @clear="clearHandle" :placeholder="placeholder" ref="select">      class="selectInput"
      placeholder="检索关键字"
      v-model="filterText">"valueTitle" :label="valueTitle" class="options">"tree-option"
        ref="selectTree"
        :accordion="accordion"
        :data="options"
        :props="props"
        :node-key="props.value"    
        :default-expanded-keys="defaultExpandedKey"
        :filter-node-method="filterNode"
        @node-click="handleNodeClick">

.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);
    }
},

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

使用组件

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

      :props="defaultProps"
      :options="treeData"
      :value="value"
      :accordion="true"
      @getValue="getValue($event)"
      placeholder="请选择所属区域"
    />选中的id:{{value}}

源码收录在公众号【小猴子的web成长之路】,关注公众号回复关键字【treeSelect】即可获取  

f9c1aad56f39043c0db43e876e48d9ef.png

 相关推荐

JavaScript 启动性能瓶颈分析与解决方案

从零看清Node源码createServer和负载均衡整个过程

【项目实战】sass使用进阶篇(下)

【项目实战】sass使用基础篇(上)

最详细的从零开始配置 TypeScript 项目的教程

5 款非常好用的开源 Docker 工具

WebSocket 全面知识补全

7个处理JavaScript值为undefined的技巧

immutablejs 是如何优化我们的代码的?

Chrome 新功能尝鲜!— CSS Overview

又一个布局利器, CSS 伪类 :placeholder-shown

封装一个vue视频播放器组件

对于组件的可重用性,大佬给出来6个建议

学习 TS 不要错过的八个工具

Node 中的全链路式日志标记及处理

使用 Node 开发服务器项目时如何高效地打日志?

用TypeScript学设计模式(享元模式)

用TypeScript学设计模式(模板方法模式)

TypeScript 设计模式之适配器模式

用TypeScript学设计模式(观察者模式)

用TypeScript学设计模式(单例模式)

0a9c06d627b20dae4a7ef659e374e374.png

04c213d51c66beb702604821ec388a52.png点在看的人特别帅/美 797ce9bede9b6f72cc95facd1bcfb4aa.gif
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值