原生js实现下拉框,支持多选、搜索
就是一些事件绑定,话不多说上代码。
使用起来的话就调用init方法
1.搜索框与选中结果同框
<!-- * @Description: * @Autour: lkx * @Date: 2023-10-07 13:47:03 * @LastEditors: lkx * @LastEditTime: 2023-12-21 20:17:25 --> <!DOCTYPE html> <html> <head> <style> .custom-select { width: 260px; position: relative; display: flex; align-items: flex-start; border: 1px solid #999; border-radius: 5px; } .custom-select-content { width: 100%; min-height: 32px; max-height: 120px; overflow-x: hidden; overflow-y: auto; } .select-input { width: 254px; height: 26px; margin-right: 20px; border: none; } .select-input:focus { outline: none; } .select-result-label { display: block; height: 32px; line-height: 32px; } .select-list { position: absolute; left: 0; bottom: 0; transform: translateY(110%); width: 260px; min-height: 32px; max-height: 120px; overflow-x: hidden; overflow-y: auto; border: 1px solid #999; border-radius: 5px; } .select-list div { padding: 2px 4px; box-sizing: border-box; } .select-list div:hover { background-color: #eee; cursor: pointer; } .selected { color: blue; } .select-result { display: flex; flex-wrap: wrap; box-sizing: border-box; } .select-result div { height: 26px; border: 1px solid #999; border-radius: 5px; padding: 3px; margin: 3px; box-sizing: border-box; display: flex; align-items: center; } .select-result div span:last-of-type { display: inline-block; border: 1px solid #999; height: 8px; width: 8px; border-radius: 100%; padding: 2px; line-height: 7px; text-align: center; font-size: 12px; margin-left: 3px; cursor: pointer; } </style> </head> <body> <div class="custom-select"> <div class="custom-select-content"> <div class="select-result select-box "></div> <input type="text" class="select-input" placeholder="搜索"> </div> <div class=" select-list select-box " style=" display: none;"></div> </div> <script> const selectContent = document.querySelector('.custom-select .custom-select-content') const selectInput = document.querySelector('.custom-select .custom-select-content .select-input') const selectList = document.querySelector('.custom-select .select-list') const selectResult = document.querySelector('.custom-select .custom-select-content .select-result') let selectInputBlurTimes = null let selectDataHit = [] let selectDataAll = [] // 事件绑定 selectInput.addEventListener('input', () => { const elList = Array.from(selectList.querySelectorAll('div')) selectList.style.display = (!selectInput.value || elList.findIndex(item => item.textContent.includes(selectInput.value)) !== -1) ? 'block' : 'none' Array.from(selectList.querySelectorAll('div')).forEach(item => { item.style.display = (!selectInput.value || item.textContent.includes(selectInput.value)) ? 'block' : 'none' }) }) document.addEventListener('click', e => { selectList.style.display = e.target.className.includes('select-input') || e.target.className.includes('select-list') || e.target.className.includes('select-result-close') || (e.target.offsetParent && e.target.offsetParent.className.includes('select-list')) ? 'block' : 'none' }) selectContent.addEventListener('click', e => { selectInput.focus() selectList.style.display = 'block' selectInput.scrollIntoView({ behavior: 'smooth', block: 'center' }) e.stopPropagation() }) // 生成下拉列表 const createSelectList = (content) => { const div = document.createElement('div') div.addEventListener('click', () => { if (selectDataHit.includes(content.value)) { selectDataHit.splice(selectDataHit.indexOf(content.value), 1) Array.from(selectResult.querySelectorAll('div span')).find(item => item.textContent === content.label).parentNode.remove() div.classList.remove('selected') } else { selectDataHit.push(content.value) createSelectResult(content) div.classList.add('selected') } }) div.textContent = content.label selectList.append(div) } // 生成选中列表 const createSelectResult = (content) => { const div = document.createElement('div') const span = document.createElement('span') span.textContent = "x" span.className = 'select-result-close' span.addEventListener('click', () => { selectDataHit.splice(selectDataHit.indexOf(content.value), 1) selectList.querySelectorAll('div')[selectDataAll.findIndex(item => item.value === content.value)].classList.remove('selected') div.remove() }) div.innerHTML = ` <span>${content.label}</span> ` div.append(span) selectResult.append(div) selectInput.scrollIntoView({ behavior: 'smooth', block: 'center' }) } // 初始化 const init = () => { selectDataAll = [{ label: '111111', value: 111111 }, { label: '222222', value: 222222 }, { label: '333333', value: 333333 }, { label: '444444', value: 444444 }, { label: '5555555', value: 5555555 }, { label: '666666', value: 1116111 }, { label: '1111711', value: 1111711 }, { label: '1111181', value: 1118111 }, { label: '1111191', value: 1911111 },] selectDataAll.forEach(item => { createSelectList(item) }) } init() </script> </body> </html>
复制
2.输入框与选中结果分离
<!-- * @Description: * @Autour: lkx * @Date: 2023-10-07 13:47:03 * @LastEditors: lkx * @LastEditTime: 2023-10-07 14:30:17 --> <!DOCTYPE html> <html> <head> <style> .custom-select { position: relative; display: flex; align-items: flex-start; } .select-input { width: 254px; height: 26px; margin-right: 20px; } .select-box { width: 260px; min-height: 32px; max-height: 120px; overflow-x: hidden; overflow-y: auto; border: 1px solid #999; border-radius: 5px; } .select-result-label { display: block; height: 32px; line-height: 32px; } .select-list { position: absolute; left: 0; top: 40px; } .select-list div { padding: 2px 4px; box-sizing: border-box; } .select-list div:hover { background-color: #eee; cursor: pointer; } .selected { color: blue; } .select-result { display: flex; flex-wrap: wrap; box-sizing: border-box; } .select-result div { height: 26px; border: 1px solid #999; border-radius: 5px; padding: 3px; margin: 3px; box-sizing: border-box; display: flex; align-items: center; } .select-result div span:last-of-type { display: inline-block; border: 1px solid #999; height: 8px; width: 8px; border-radius: 100%; padding: 2px; line-height: 7px; text-align: center; font-size: 12px; margin-left: 3px; cursor: pointer; } </style> </head> <body> <div class="custom-select"> <input type="text" class="select-input" placeholder="搜索"> <div class="select-list select-box " style="display: none;"></div> <span class="select-result-label">选中结果:</span> <div class="select-result select-box "></div> </div> <script> const selectInput = document.querySelector('.custom-select .select-input') const selectList = document.querySelector('.custom-select .select-list') const selectResult = document.querySelector('.custom-select .select-result') let selectInputBlurTimes = null let selectDataHit = [] let selectDataAll = [] // 事件绑定 selectInput.addEventListener('input', () => { const elList = Array.from(selectList.querySelectorAll('div')) selectList.style.display = (!selectInput.value || elList.findIndex(item => item.textContent.includes(selectInput.value)) !== -1) ? 'block' : 'none' Array.from(selectList.querySelectorAll('div')).forEach(item => { item.style.display = (!selectInput.value || item.textContent.includes(selectInput.value)) ? 'block' : 'none' }) }) document.addEventListener('click', e => { selectList.style.display = e.target.className.includes('select-input') || e.target.className.includes('select-list') || e.target.className.includes('select-result-close') || (e.target.offsetParent && e.target.offsetParent.className.includes('select-list')) ? 'block' : 'none' }) // 生成下拉列表 const createSelectList = (content) => { const div = document.createElement('div') div.addEventListener('click', () => { if (selectDataHit.includes(content.value)) { selectDataHit.splice(selectDataHit.indexOf(content.value), 1) Array.from(selectResult.querySelectorAll('div span')).find(item => item.textContent === content.label).parentNode.remove() div.classList.remove('selected') } else { selectDataHit.push(content.value) createSelectResult(content) div.classList.add('selected') } }) div.textContent = content.label selectList.append(div) } // 生成选中列表 const createSelectResult = (content) => { const div = document.createElement('div') const span = document.createElement('span') span.textContent = "x" span.className = 'select-result-close' span.addEventListener('click', () => { selectDataHit.splice(selectDataHit.indexOf(content.value), 1) selectList.querySelectorAll('div')[selectDataAll.findIndex(item => item.value === content.value)].classList.remove('selected') div.remove() }) div.innerHTML = ` <span>${content.label}</span> ` div.append(span) selectResult.append(div) } // 初始化 const init = () => { selectDataAll = [{ label: '111111', value: 111111 }, { label: '222222', value: 222222 }, { label: '333333', value: 333333 }, { label: '444444', value: 444444 }, { label: '5555555', value: 5555555 }, { label: '666666', value: 1116111 }, { label: '1111711', value: 1111711 }, { label: '1111181', value: 1118111 }, { label: '1111191', value: 1911111 },] selectDataAll.forEach(item => { createSelectList(item) }) } init() </script> </body> </html>
复制