自定义的可分类可搜索的下拉框组件

效果图

 

 注:值是根据原生select中的值来动态获取并进行分类

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>index</title>
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <div class="container">
      <div id="wrap">
      <div class="div1">
        <div class="title">自定义select</div>

        <div class="select">
          <select id="select-name">
            <option value="" disabled="true">请选择</option>

          </select>
          <div class="s select-box">
            <div class="s select-head">
              <span class="s">未选择</span>
              <i class="s"></i>
            </div>
            <div class="s select-body">
              <div class="s search-input">
                <input class="s" type="text" placeholder="搜索">
                <i class="s"></i>
              </div>
              <div class="s value-body">

              </div>
            </div>
          </div>
        </div>

      </div>
      <div class="outdiv">
        <p id="out"></p>
      </div>

    
      <div class="div2">
        <div class="title">原生select</div>
        <select>
          <option value="1" type="构建工具">Babel</option>
          <option value="2" type="构建工具">Webpack</option>
          <option value="3" type="构建工具">Rollup</option>
          <option value="4" type="前端框架">Vue</option>
          <option value="5" type="前端框架">Angular</option>
          <option value="6" type="前端框架">React</option>
          <option value="7" type="前端框架">Nerv</option>
        </select>
      </div>
    </div>
  </div>
  <script src="index.js"></script>
</body>
</html>

style.css

.container{
    width:100%;
    height:100vh;
    text-align: center;
}
#wrap{
    height:170px;
    position: relative;
    top:50%;
    margin-top:-85px;
    text-align: center;
}
.div1{
    text-align: center;
}
.div2{
    text-align: center;
}
.title{
    color: rgb(75,151,251);
    margin-bottom: 10px;
}
div.select{
    width: 200px;
    position: relative;
    left: 50%;
    margin-left: -100px;
}
div.select select{
    display: none;
}

div.select-box{
    width: 200px;
    margin: 20px 20px;
}

div.select-head{
    position: relative;
    height: 30px;
    width: 100%;
    display: flex;
    border: solid 1px rgb(75,151,251);
    align-items: center;
    cursor: pointer;
}

div.select-head span{
    font-size: 16px;
    margin-left: 5px;
    color: #AAA;
}

div.select-head span.fill{
    color: #000;
}

div.select-head i{
    position: absolute;
    height: 30px;
    width: 30px;
    right: -1px;
    background: url(./arrow.png) center center no-repeat;
    background-size: 30px auto;
}

div.select-body{
    display: none;
    width: 100%;
    border: solid 1px rgb(75,151,251);
    border-top: none;
}

div.search-input{
    position: relative;
    height: 40px;
}

div.search-input input{
    height: 30px;
    width: 150px;
    margin: 5px 8px;
    text-indent: 10px;
    padding-right: 30px;
}

div.search-input i{
    position: absolute;
    display: block;
    height: 20px;
    width: 20px;
    top: 12px;
    right: 15px;
    background-image: url(./search-normal.png);
    background-size: 20px 20px;
    cursor: pointer;
}

div.search-input i:hover{
    background-image: url(./search-active.png);
}

div.value-body{
    max-height: 150px;
    overflow-y: auto;
    text-align: left;
    overflow-x: hidden;
}

div.value-body li{
    display: flex;
    height: 24px;
    padding: 5px 5px 5px 30px;
    font-size: 14px;
    align-items: center;
    cursor: pointer;
    position: relative;
}

div.value-body span{
    display: block;
    font-weight: bold;
    font-size: 16px;
    margin:10px;
}

div.value-body span+li{
    margin-top: 14px;
}

div.value-body li:hover,li.active{
    background-color: #F5F6FA;
}

div.value-body li.active{
    background-color: rgb(75,151,251);
    color:white;
}

div.value-body li.none,div.none{
    display: none;
}

div.value-body div{
    text-align: center;
    height: 30px;
    line-height: 30px;
    color: #AAA;
}

index.js

    window.onload = function () {

      //初始化生成DOM元素
      function init(){
        var types=[];
        // 根据原生的select中的每一项提供的类型和值,使用脚本获取,然后进行分类重新显示
        var options=document.querySelectorAll('.div2 option');
        var templates='';//插入到select的总模板
        var se_templates='';//插入到div的总模板
        var tem='';//select 某个分类的总模板
        var se_tem='';//div 某个分类的总模板

        options.forEach( function(element, index) {
            var type=element.getAttribute('type');

            //创建分类
            if (types.indexOf(type)==-1){
              types.push(type)

              tem=`<span>`+type+`</span>`;
              se_tem=`<span>`+type+`</span>`;

              var lis='';//select 某个分类下的项目模板
              var se_lis='';//div 某个分类下的项目模板

              //根据分类创建选项
              options.forEach( function(ele) {
                var value=ele.getAttribute('value');
                var text=ele.innerText;
                if(ele.getAttribute('type')==type){
                  lis+=`<li data-value="`+text+`">`+text+`</li>`;
                  se_lis+=`<option value="`+text+`">`+text+`</option>`;
                }             
              });
              tem+=lis;
              se_tem+=se_lis;
              templates+=tem; 
              se_templates+=se_tem; 
            }
                        
          });
        
        document.querySelector('.value-body').innerHTML=templates;
        document.querySelector('#select-name').innerHTML=se_templates;       
      }
      init();

      var out=document.querySelector('#out');
      var last_out='未选择--undefined';


      //清空select的value
      document.querySelector('div.select>select').value = ''

      /**
       * 点击自定义的select框开启或收回选择框
       */
      document.querySelector('div.select-head').onclick = function () {
        //清空输入框内容
        document.querySelector('div.search-input>input').value = ''

        document.querySelectorAll('div.value-body>li').forEach( function(element, index) {
          if (element.classList.contains('active')) {
            element.classList = 'active'
          }else {
            element.classList = ''
          }
        });

        // document.querySelector('div.value-body>div').classList = 'none'

        var select_body = document.querySelector('div.select-body')
        if (select_body.style.display == 'block') 
          select_body.style.display = 'none'
        else 
          select_body.style.display = 'block'
      };

      /**
       * 点击空白处关闭select框
       */
      document.onclick = function (argument) {
        if(!argument.target.classList.contains('s')){
          var select_body = document.querySelector('div.select-body')
          if (select_body.style.display == 'block') 
            select_body.style.display = 'none'
        }
      }

      /**
       * 自定义的select的选值功能
       */
      document.querySelectorAll('div.value-body>li').forEach( function(element, index) {
        element.onclick = function () {
          //初始化下样式
          document.querySelectorAll('div.value-body>li').forEach( function(element, index) {
            element.classList = ''
          });
          element.classList = 'active'
          //更新select框的value和自定义的select框的value
          var data_value = element.getAttribute('data-value')
          var select_head_span = document.querySelector('div.select-head>span')
          document.querySelector('div.select>select').value = data_value
          select_head_span.innerHTML = data_value
          out.innerHTML= '之前的值是:'+last_out+'<br>改变后的值是:'+data_value
          last_out=data_value;
          if(!select_head_span.classList.contains('fill'))
            select_head_span.classList = 'fill'

          //关闭select-body
          document.querySelector('div.select-body').style.display = 'none'
        }
      });

      /**
       * 搜素功能实现
       */
      document.querySelector('div.search-input>input').oninput = function () {
        var input_value = document.querySelector('div.search-input>input').value
        if(input_value == '') {
          document.querySelectorAll('div.value-body>li').forEach( function(element, index) {
            if (element.classList.contains('active')) {
              element.classList = 'active'
            }else {
              element.classList = ''
            }
          });
        }else{
          document.querySelectorAll('div.value-body>li').forEach( function(element, index) {
            if(element.getAttribute('data-value').toLowerCase().indexOf(input_value.toLowerCase()) == -1){
                if (element.classList.contains('active')) {
                  element.classList += ' none'
                }else {
                  element.classList = 'none'
                }
            }else {
              if(element.classList.contains('none')) {
                document.querySelectorAll('div.value-body>li').forEach( function(element, index) {
                  if (element.classList.contains('active')) {
                    element.classList = 'active'
                  }else {
                    element.classList = ''
                  }
                });
              }
            }
          });
        }
        //记一下结果数量
        var length = 0
        document.querySelectorAll('div.value-body>li').forEach( function(element, index) {
          if (!element.classList.contains('none')) length++
        });
        
        if (length == 0) {
          document.querySelector('div.value-body>li').classList = ''
        }else{
          document.querySelector('div.value-body>li').classList = 'none'
        }
      }


    };
posted @ 2020-01-19 19:52  陈莺莺呀  阅读(1121)  评论(0编辑  收藏  举报