自定义的可分类可搜索的下拉框组件
效果图
注:值是根据原生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' } } };