欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

自己写下拉复选框组件

程序员文章站 2024-01-02 13:51:10
...

需求:下拉框,能够支持多个选择

如图,样式自己可以调整

自己写下拉复选框组件

思路:

1、需要一个最外层,包裹放值得输入框以及下拉组件

2、可以用flex布局,上下放输入框和下拉组件,也可以定位下拉组件

3、下拉组件用的ul li,li里包裹着input类型为checkbox的框,以及span展示值,这里有点需要优化,点当行应该都选中框,现在是点框才勾选

4、默认值是当前价,可以存一个全局变量,value=['0'],也可以在存一个值得data=['当前价'],后端要的是0这种形式也就是value,前端展示在框的是data这样的数据,当然也可以用对象[{value:'0',name:'当前价'}]这种数据结构存,也比较正规一些,我这里用二个数组来说明

5、拿到data值后,要回显到框里,并且要自动勾选符合的框,回显框里的值可以用data.join(','),框可以取li 下面的input,遍历元素,把input的value值和data或者value对比,这里看你存的什么,比如data.includes*(input.value)为true,input.checked = true,就把框选中了

  • 下面看一下代码

下拉组件数据

listData={
   '0':'当前价',     //默认显示
   '1':'成交总量',
   '2':'成交总额',
   '3':'持仓量',
   '8':'开盘价',
   '9':'最高价',
   'a':'最低价',
   'd':'多档委买卖价量',
   'e':'多档委买卖价'
}

  • html
  1. 整个结构图参考

自己写下拉复选框组件

 

<div class="right push_fields">
    <input type="text" data-type="push_fields" value="当前价" data-value="0">
    <ul class="selectList"></ul>
</div>

 

其他代码我动态加进去的,js,效果如上图

//渲染下拉复选框
createMultiSelect(){
   let html='' ;
   for(let i in this.data.listData){
      if(this.data.listData.hasOwnProperty(i)){
          html+=`<li>
                  <input data-value='${i}' value='${this.data.listData[i]}' type='checkbox'>
                  <span title="${this.data.listData[i]}">${this.data.listData[i]}</span>
               </li>`
      }
   }
   //根据自己的项目情况来动态添加
   $(html).appendTo(this.el.find('.selectList'))
   //默认选中第一个,这个方法是很笨的,后面说一种基于值去遍历自动勾选符合的,灵活的方法
   this.el.find('ul li').eq(0).find('input:checkbox')[0].checked = true
},

 

  • 下面是一些js逻辑

回显的数据逻辑,因为我这里是几个tab,所以根据tab来显示不同的数据,大家只有一个的话,就少了一些判断

//切换tab的时候,下拉复选框的选中状态 根据名称得集合遍历选框 在集合里的就选中
changeTabOfSelectChecked(id){
   let lis = this.el.find(`.from div.${id} li input`)//该tab下的input选框集合
   let data = id=='level1'?this.data.value:this.data.value1;//判断是哪个tab,并拿到值集合
          for(let i of lis){
//循环选框集合,拿到的是原生的
//直接可以获取value或者你自己自定义值判断是否包含在总数据里,在的话就勾选上
              i.checked = data.includes(i.value)?true:false
          }
          //因为切换tab,下拉复选框的值跟着变化,不然二个tab的展示总值的input串值了
          this.el.find('.push_fields input[type="text"]').val(data.join(','))
},

 

  • 下拉框展示隐藏的切换方法,也可以用is(:visible)这种方式判断,大家用自己熟悉的点击事件来写就好

{//下拉框切换
 event:'click',
   selector:'.push_fields',
   callback:function () {
              this.el.find('.selectList').toggle()
          }
},
  • 选框被点击的时候的事件,这里可以加一下选中文字也勾选选框,目前效果是点选框才被勾选

{
    event: 'click',
    selector: 'li',
    callback: _.debounce(function (context) {
        this.actions.selectItem($(context));
    }, 50)
},

 

  • 接上一个,点击选框后具体的逻辑

//选中的选项
      selectItem(item){
          //当前选框状态 true or false
          let checked  = item.find('input:checkbox')[0].checked;
          //当前框的值,我自己定义的data-value,这个要传给后台保存
          let value = item.find('input:checkbox').data().value;
          //当前框的名称,这是要展示在页面输入框的
   let name = item.find('input:checkbox').val();
   //根据不同tab下保存该值,数据结构大家可以更规范一些
   if(this.data.postData.level =='level1'){
      let data = this.actions.renderSelects(checked,value,name,this.data.choose,this.data.value)
      this.data.choose = data.choose//更新最后的勾选得值,需要传给后台
      this.data.value = data.data//更新最后需要展示在页面,输入框的值
   }
   else if (this.data.postData.level =='level2') {
              let data = this.actions.renderSelects(checked,value,name,this.data.choose1,this.data.value1)
              this.data.choose1 = data.choose
              this.data.value1 = data.data
   }
},

 

  • 接上一个逻辑里单独提出来的逻辑

 

/**
 * 根据不同tab保存展示的值和传给后台的值
 * checked:选中还是取消
 * value:当前被选中、取消的值,比如0,1
 * name:当前被选中、取消的名称,比如当前价
 * choose:当前被选中、取消的值数组,比如['0','1']
 * data:当前被选中、取消的名称数组,比如['当前价']
 * return{ choose,data }
 * **/
renderSelects(checked,value,name,choose,data){
          if (checked) {//如果是勾选,就把值存进对应的变量里,这里我判断了一下,避免存重
              !choose.includes(value)&&choose.push(value)
              !data.includes(name)&&data.push(name)
          }
          else{//如果是取消勾选,把值删除 筛选掉
              choose =this.actions.deleteArrField(value,choose)
              data= this.actions.deleteArrField(name,data)
          }
          //展示在输入框的值,可以直接用数组的join方法拼接
          this.el.find('.push_fields input[type="text"]').val(data.join(','))
          //返回值,方便更新
   return {choose,data}
},

 

  • 接上一个逻辑里单独提出来的函数

/*
* *筛选数组里的值,主要是删除取消勾选的值
* *value :需要删除的值
* arr :数组
* return:arr 最后的数组
*/
deleteArrField(value,arr){
          arr = arr.filter((name)=>{
              return name!=value
          })
   return arr
},

到此,可以用了,还可以继续优化,比如点击文字也可以勾选或者取消,比如鼠标移入有背景色以及箭头符号等,简单的下拉复选框组件到此

 

  • 下面是css 用的scss,样式可根据自己的调节

 

.push_fields {
    //display: flex;
    flex-direction: column;
    align-items: flex-start!important;
    .selectList {
        border: 1px solid #ddd;
        overflow: auto;
        margin-top: -1px;
        display: none;
        width: 240px;
        background-color: #fff;
        left: 0;
        top: calc(100% - 1px);
        z-index: 1;
        box-sizing: border-box;
        ul {
            user-select: none;
            overflow: auto;
            box-sizing: border-box;
            background-color: #fff;
            height: calc(100% - 30px);
            margin: 0;
            padding: 0;
            li {
                height: 30px;
                line-height: 30px;
                cursor: pointer;
                &.hovered {
                    background: #ddd !important;
                }
                input.checkbox {
                    vertical-align: top;
                    margin: 9px 0 0 8px;
                    visibility: hidden;
                }
                span {
                    margin: 0 !important;
                    padding-left: 8px;
                    display: inline-block;
                    box-sizing: border-box;
                    flex: 0 0 calc(100% - 40px);
                    overflow: hidden;
                    white-space: nowrap;
                    text-overflow: ellipsis;
                }
            }
        }
    }
}

有时间再出优化版本

上一篇:

下一篇: