如何实现自定义下拉组件,select下拉框样式自定义,带搜索的select下拉框

  • 1.实现的效果
  • 2.实现说明
  • 3.完整代码

一、实现的效果:

在这里插入图片描述
在这里插入图片描述

二、实现说明:

1.由于无法修改原生select中的option样式,因此自己通过ul,li实现下拉列表,用input实现回显框;
input实现select回显注意2个地方:
1)使用 readonly=“readonly” 让input框无法实现输入 ,不获取焦点;

<input type="text" readonly="readonly" class="ec-input__value" placeholder="业务类型" value="" id="yewu-value">

2)当需要input框可以输入时,使用autocomplete=“new-password” 避免input框获取焦点时自动以下拉的方式弹出以前输入过的值,导致覆盖真正需要展示的下拉列表

 <input type="text" autocomplete="new-password" class="ec-input__value" placeholder="请选择国家地区" value="" id="area-value" oninput="enterSearch(this)">

2.下拉框的弹出与隐藏
1)没有显示时点击input部分弹出(同时右侧三角箭头改变,朝上),当弹出框以及显示点击隐藏下拉弹出框(三角箭头方向恢复,朝下)
实现弹出下拉列表代码如下:

   //自定义下拉框弹出事件
  function openValue(obj, e){
    e.stopPropagation(); //阻止冒泡
    //阻止默认浏览器动作(W3C)
    if ( e && e.preventDefault ){
      e.preventDefault();
    } else{
      window.event.returnValue = false;
    }
    if ($(".dropdown-menus").is(":visible")) {
      $('.dropdown-menus').hide();
      $('.ec-input').removeClass('ec-input__open');
    }else{
      $(obj).addClass('ec-input__open');
      $(obj).next().show();
    }
  }

右侧三角箭头

 .caret{
    display: inline-block;
    width: 0;
    height: 0;
    margin-left: 2px;
    vertical-align: middle;
    border-top: 4px dashed;
    border-top: 4px solid;
    border-right: 4px solid transparent;
    border-left: 4px solid transparent;
  }
  .ec-input .caret {
    position: absolute;
    top: 50%;
    right: 12px;
    margin-top: -2px;
    vertical-align: middle;
   }
   .ec-input__open .caret{
     transform: rotate(180deg);
   }

2)选中下拉框的某一个值之后,值回显,弹出框隐藏;
注意:由于使用事件委托的方式,当点击某一个选项时,有可能点击的target不是li节点,而是li的子节点,此时可以取其父节点

 // 点击的地方可能是li,也可能是li的子节点
    if(e.target && e.target.nodeName == "LI"){
      selectedDom = e.target;
    }else{
      selectedDom = $(e.target).parent();
    }

事件的完整代码如下:

   //点击某个下拉菜单的值之后的事件处理
  function getValue(obj, e){
    e.stopPropagation(); //阻止冒泡
    var selectedDom;
    // 点击的地方可能是li,也可能是li的子节点
    if(e.target && e.target.nodeName == "LI"){
      selectedDom = e.target;
    }else{
      selectedDom = $(e.target).parent();
    }
    var selectedValue = $(selectedDom).data('value');
    var selectedLable = $(selectedDom).data('label');
    var operId = $(obj).data('id');
    $(selectedDom).siblings().removeClass('ec-active')
    $(selectedDom).addClass('ec-active');
    $('#'+operId+'-value').val(selectedLable);
    $('#'+operId+'-label').val(selectedValue);
    $('.ec-input').removeClass('ec-input__open');
    $(obj).parent().hide();
  }

3)当下拉弹出框显示时,点击下拉组件以外的部分,弹出框隐藏,代码如下:

 // 自定义下拉框:点击其他部分收起下拉事件
  document.addEventListener("click", (e) => {
    if ($(".dropdown-menus").is(":visible")) {
      $('.dropdown-menus').hide();
      $('.ec-input').removeClass('ec-input__open');
    }
  });

3.带搜索的下拉框,当中文输入法输入中文时,让其回显中文时实现搜索,而非输入每次输入都执行一次搜索操作,代码如下:

   // 中文输入法
    $('.ec-input__value').on('compositionstart',function(event) {
      isChinese = true;
		})
    //  输入中文之后
    $('.ec-input__value').on('compositionend',function() {
      isChinese = false;
      enterSearch(this)
    })

三、完整代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>自定义下拉组件</title>
</head>
<style>
    body, p{
        margin:0;
        padding:0;
    }
    .container{
      margin:100px;
    }
    .askForm{
        margin:20px;
        display: flex;
        display: -webkit-flex;
        background: #fff;
        border:1px solid #e1e1e1;
        border-radius: 6px;
        height: 34px;
    }
    .select-left{
        flex:2;
    }
    .select-right{
        flex: 3;
        padding-right: 10px;
    }
    .ec-select{
        height: 34px;
    }
    .select-online{
        width: 20px;
        margin-right: 10px;
        height: 20px;
        margin-top:7px;
        border-right: 1px solid #e1e1e1;
    }
  .ec-input{
    width: 100%;
    height: 34px;
    line-height: 34px;
    padding-left: 10px;
    position: relative;
  }
  .ec-input .ec-input__value{
    border: none;
    outline: none;
    width: 90%;
    cursor: pointer;
  }
  .caret{
    display: inline-block;
    width: 0;
    height: 0;
    margin-left: 2px;
    vertical-align: middle;
    border-top: 4px dashed;
    border-top: 4px solid;
    border-right: 4px solid transparent;
    border-left: 4px solid transparent;
  }
  .ec-input .caret {
    position: absolute;
    top: 50%;
    right: 12px;
    margin-top: -2px;
    vertical-align: middle;
   }
   .ec-input__open .caret{
     transform: rotate(180deg);
   }
  .dropdown-menus{
      position: relative;
      max-height: 200px;
      width: 100%;
      display: none;
      border: 1px solid rgba(0,0,0,.15);
      border-radius: 4px;
      -webkit-box-shadow: 0 6px 12px rgb(0 0 0 / 18%);
      box-shadow: 0 6px 12px rgb(0 0 0 / 18%);
      overflow-y: scroll;
      overflow: auto;
      min-height: 42px;
  }
  .dropdown-menu{
    padding:6px 0;
    margin:0;
    list-style: none;
  }
  .menu-item{
    height: 30px;
    cursor: pointer;
    line-height: 30px;
    padding-left: 10px;
  }
  .menu-item:hover{
    outline: 0;
    color:#FF9500;
    background: rgba(255, 149, 0, 0.1);
  }
  .select-ok{
    position: absolute;
    display: inline-block;
    right: 15px;
    margin-top: 8px;
  }
  .ec-active .select-ok{
    width: 14px;
    height: 6px;
    display: inline-block;
    border: 1px solid #FF9500;
    border-width: 0 0 2px 2px;
    transform: rotate(-45deg);
    -ms-transform: rotate(-45deg);
    -moz-transform: rotate(-45deg);
    -webkit-transform: rotate(-45deg);
    -o-transform: rotate(-45deg);
    vertical-align: baseline;
  }
  .no-result{
    padding: 8px;
  }
</style>
<body>
  <div class="container">
    <div class="askForm">
        <div class="select-container select-left">
            <div class="ec-input" onclick="openValue(this,event)">
              <input type="hidden" value="" id="yewu-label">
              <input type="text" readonly="readonly" class="ec-input__value" placeholder="业务类型" value="" id="yewu-value">
              <span class="caret"></span>
            </div>
            <div class="dropdown-menus">
              <ul class="dropdown-menu" onclick="getValue(this, event)" data-id="yewu">
                <li class="menu-item" data-value="0" data-label="专线"><span class="text">专线</span><span class="select-ok"></span></li>
                <li class="menu-item ec-active" data-value="1" data-label="系统通知"><span class="text">系统通知</span><span class="select-ok"></span></li>
                <li class="menu-item" data-value="2" data-label="版本发布"><span class="text">版本发布</span><span class="select-ok"></span></li>
              </ul>
            </div>
        </div>
        <div class="select-online"></div>
        <div class="select-container select-right">
            <div class="ec-input" onclick="openValue(this,event)">
              <input type="hidden" value="" id="area-label">
              <input type="text" class="ec-input__value" autocomplete="new-password" placeholder="请选择国家地区" value="" id="area-value" oninput="enterSearch(this)">
              <span class="caret"></span>
            </div>
            <div class="dropdown-menus area-menus">
            </div>
        </div>
    </div>
  </div>
</body>
<script src="http://cdn.staticfile.org/jquery/2.1.1/jquery.min.js" type="text/javascript"></script>
<script>
  var earaData = [
    {name:'中国'},
    {name:'泰国'},
    {name:'美国'},
    {name:'英国'},
    {name:'日本'},
    {name:'澳大利亚'},
    {name:'韩国'},
    {name:'印度尼西亚'},
  ];
  var filterArea = [];
  var isChinese = false;
  searchArea('');//初始化国家地区dom
   //自定义下拉框弹出事件
  function openValue(obj, e){
    e.stopPropagation(); //阻止冒泡
    //阻止默认浏览器动作(W3C)
    if ( e && e.preventDefault ){
      e.preventDefault();
    } else{
      window.event.returnValue = false;
    }
    if ($(".dropdown-menus").is(":visible")) {
      $('.dropdown-menus').hide();
      $('.ec-input').removeClass('ec-input__open');
    }else{
      $(obj).addClass('ec-input__open');
      $(obj).next().show();
    }
  }
   //点击某个下拉菜单的值之后的事件处理
  function getValue(obj, e){
    e.stopPropagation(); //阻止冒泡
    var selectedDom;
    // 点击的地方可能是li,也可能是li的子节点
    if(e.target && e.target.nodeName == "LI"){
      selectedDom = e.target;
    }else{
      selectedDom = $(e.target).parent();
    }
    var selectedValue = $(selectedDom).data('value');
    var selectedLable = $(selectedDom).data('label');
    var operId = $(obj).data('id');
    $(selectedDom).siblings().removeClass('ec-active')
    $(selectedDom).addClass('ec-active');
    $('#'+operId+'-value').val(selectedLable);
    $('#'+operId+'-label').val(selectedValue);
    $('.ec-input').removeClass('ec-input__open');
    $(obj).parent().hide();
  }
 //国家地区搜索框输入事件
  function enterSearch(obj){
    if(!isChinese){
      var key = $(obj).val();
      searchArea(key);
    }
  }
   // 下拉搜索框搜索事件
  function searchArea(key){
    filterArea = [];
    for(var j = 0,len=earaData.length;j<len;j++){
      if(earaData[j].name.match(key)){
        filterArea.push(earaData[j].name)
      }
    }
    appendSelectArea(key);
  }
    // 中文输入法
    $('.ec-input__value').on('compositionstart',function(event) {
      isChinese = true;
		})
    //  输入中文之后
    $('.ec-input__value').on('compositionend',function() {
      isChinese = false;
      enterSearch(this)
    })
    // 将搜索到的结果重新渲染到下拉框中
  function appendSelectArea(key){
    var areasHtml = '';
    if(filterArea && filterArea.length>0){
      areasHtml = '<ul class="dropdown-menu" οnclick="getValue(this, event)" data-id="area">';
      for(var i = 0,len = filterArea.length ;i<len;i++){
        areasHtml+='<li class="menu-item" data-value='+filterArea[i]+' data-label='+filterArea[i]+'><span class="text">'+filterArea[i]+'</span><span class="select-ok"></span></li>'
      }
      areasHtml+='</ul>';
    }else{
      areasHtml = '<div class="dropdown-menu no-result" data-id="area"> 很抱歉没有找到“'+key+'”相关结果!</div>';
    }
    $('.area-menus').html(areasHtml);
  }
  // 自定义下拉框:点击其他部分收起下拉事件
  document.addEventListener("click", (e) => {
      if ($(".dropdown-menus").is(":visible")) {
        $('.dropdown-menus').hide();
        $('.ec-input').removeClass('ec-input__open');
      }
    });
</script>
</html>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值