javascript - 如何添加动态监听器并获取目标值

标签 javascript html css

我创建了一个自定义下拉列表,并希望获取其中被点击元素的文本内容。

下拉元素和事件监听器一样是动态创建的,但监听器似乎无法正常工作。

下拉示例:

Dropdown example

我可以在开发工具中的每个 div 上看到监听器。

子div的事件监听器:

Event listener of child 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):

Event Delegation on click of child div

我是不是漏掉了什么?

更新

感谢@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/

相关文章:

html - 如何在不对文本应用居中格式的情况下将页面主体中的所有元素居中?

javascript - 动画不适用于列表项

asp.net - 无法对齐 div

angularjs - 为什么 P 标签不占据行的整个高度?

javascript - 当 html 文件中遇到 &lt;script&gt; 标签时会发生什么?

javascript - 绕一圈

javascript - jQuery 函数与事件的公因数

javascript - 如何通过html将参数传递给函数并通过javascript访问?

javascript - Facebook graph api JSONP格式,第一行的/* */是什么意思?

html - li::before 中图像前不需要的空间