原生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>