我创建了一个自定义下拉列表,并希望获取其中被点击元素的文本内容。
下拉元素和事件监听器一样是动态创建的,但监听器似乎无法正常工作。
下拉示例:
我可以在开发工具中的每个 div 上看到监听器。
子div的事件监听器:
下拉列表中的第一个 div 用它的值填充输入,但其他的不填充。
(function() {
let departments = ['Accounting', 'Human Resources', 'IT', 'Warehouse'];
let element = document.getElementById('dd-Department');
departments.forEach(v => {
let div = document.createElement('div');
div.appendChild(document.createTextNode(v));
div.addEventListener('click', () => {
element.parentNode.querySelector('input').value = v;
});
element.appendChild(div);
});
})();
.form-question {
display: flex;
flex-direction: column;
justify-content: center;
margin: 0 0 3rem;
min-height: 3rem;
}
.form-question__title {
color: #342357;
font-size: 1.5rem;
padding: 1rem;
}
.input-container {
border-bottom: solid 2px #333333;
position: relative;
}
input[readonly] {
cursor: pointer;
}
.input-container input {
border: none;
box-sizing: border-box;
outline: 0;
padding: .75rem;
position: relative;
width: 100%;
}
.input-container:focus-within .dropdown {
transform: scaleY(1);
}
.dropdown {
background: #ffffff;
box-shadow: 0 5px 12px #333333;
left: 0;
max-height: 300px;
overflow-y: auto;
padding: 0;
position: absolute;
right: 0;
top: calc(100% + 2px);
transform: scaleY(0);
transform-origin: top;
transition: transform .3s;
z-index: 10;
}
.dropdown div {
border-bottom: 2px solid #777777;
cursor: pointer;
padding: 8px;
z-index: 20;
}
.dropdown div:hover {
background: #dddddd;
font-weight: 800;
}
<div class="form-question">
<div class="form-question__title">
<span>Department</span>
</div>
<div class="form-question--dropdown input-container">
<input type="text" name="Department" readonly="readonly"></input>
<div id="dd-Department" class="dropdown"></div>
</div>
</div>
我也尝试了事件委托(delegate),但是无法获取点击的div的文本内容。目标是预期 div 的父级,因此文本内容是所有子值的组合。
let element = document.getElementById('dd-Department');
element.addEventListener('click', e => {
if (e.target && e.target.classList.contains('dropdown')) {
e.target.parentNode.parentNode.querySelector('input').value = e.target.textContent;
}
}, true);
点击子 div 的事件委托(delegate):
我是不是漏掉了什么?
更新
感谢@dawn 指出问题所在。 我通过改变来解决这个问题
.input-container:focus-within .dropdown
到
.input-container.active .dropdown
并使用 javascript 添加事件类。
document.querySelectorAll('.input-container').forEach(v => {
v.onclick = () => v.classList.toggle('active');
});
现在的问题是,点击输入容器以外的任何东西时,下拉菜单仍然处于事件状态。
下面的工作但感觉像是 hack。
document.querySelectorAll('.input-container').forEach(v => {
v.addEventListener('focus', () => v.classList.add('active'), true);
v.addEventListener('blur', () => setTimeout(() => v.classList.remove('active'), 75), true);
});
还有更优雅的解决方案吗?
最佳答案
这种情况是css的问题,当你点击div时,首先触发的是“transform: scaleY(0)”,而“.dropdown”已经不可见,所以无法触发点击事件。
不要使用input:focus-within来控制下拉框的Visibility,因为当你点击下拉框时,input已经失去焦点。
关于javascript - 如何添加动态监听器并获取目标值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51434508/