【问题标题】:Editing the textContent or innerHTML kills eventListener编辑 textContent 或 innerHTML 会杀死 eventListener
【发布时间】:2016-01-28 19:11:54
【问题描述】:

我是从 js 开始的,所以请原谅我明显的错误。我正在尝试使用几个可设置样式标记的选项来重新创建选择输入。

简要说明我想要做什么:

  1. 隐藏选择
  2. 使用第一个选项的文本创建一个父 div 并附加它而不是原来的隐藏选择。
  3. 在点击时添加 eventListener 以切换类(它显示和隐藏子元素)
  4. 使用来自原始隐藏选择的选项的值和文本创建内部 div。
  5. 为它们中的每一个添加 eventListener 以替换 select 的值。

这几行 js 和几行 css 让我很容易选择样式。

// Define select and options
var select = document.getElementById('select');
var children = select.children;

// Recreate select via divs and keep same class
select.style.display = 'none';
var selectNew = document.createElement('div');
selectNew.className = select.classList;
selectNew.textContent = select.children[0].text;
select.parentNode.insertBefore(selectNew, select);
selectNew.addEventListener('click', function() {
  toggleChildren();
});

function toggleChildren() {
  selectNew.classList.toggle('active');
}

// remap children
var childArray = [];
for (var i = 0; i < children.length; i++) {
  var child = document.createElement('div');
  child.innerHTML = select.children[i].text;
  child.dataset.value = select.children[i].value;
  selectNew.appendChild(child);
  childArray.push(child);

  child.addEventListener("click", function () {
    selectChoice();
  });
}

function selectChoice() {
  var which = childArray.indexOf( event.target || event.srcElement);
  select.value = children[which].value;
  // selectNew.textContent = children[which].text;
}
.select {
  position: relative;
  width: 100%;
  line-height: 3em;
  background: #eee;
}
.select > div {
  position: absolute;
  display: none;
  width: 100%;
}
.select > div:nth-child(1) {
  top: 2em;
}
.select > div:nth-child(2) {
  top: 4em;
}
.select > div:nth-child(3) {
  top: 6em;
}
.select > div:nth-child(4) {
  top: 8em;
}
.select > div:nth-child(5) {
  top: 10em;
}
.select > div:hover {
  background: #eee;
}
.select.active > div {
  display: block;
}
<select name="sortby" id="select" class="select">
  <option value="val1">Value 1</option>
  <option value="val2">Value 2</option>
  <option value="val3">Value 3</option>
  <option value="val4">Value 4</option>
  <option value="val5">Value 5</option>
</select>

每当我尝试通过以下方式更新父元素内的文本以显示所选选项的文本时:

selectNew.textContent = children[which].text;

它会杀死之前为此元素添加的事件监听器。有人可以帮助我了解我做错了什么吗?我在 eventListeners 的行为中缺少什么?

【问题讨论】:

  • 非常感谢!正如我所说,我现在正在盯着看,一开始很困难,但很有趣。为什么这个不工作很容易回答吗? select.addEventListener('change', function() { alert('select changed'); })再次感谢您

标签: javascript forms select input


【解决方案1】:

您引用的行确实会导致问题,但不是因为它会杀死侦听器。它实际上用文本替换了 selectNew 的全部内容。 您想要的是替换第一个孩子的文本,即 textContent 节点。

如果将行更改为:

selectNew.firstChild.textContent = children[which].text;

然后一切都按预期进行。

JSFiddle here.

回答有奖 至于添加监听器以更改事件的附加问题: 您不能只在 div 上使用侦听器来处理“更改”事件,只能在输入等表单元素上使用。

但是,您可以检测点击处理程序内部的更改,如下所示:

function selectChoice() {
    var which = childArray.indexOf(event.target || event.srcElement);
    select.value = children[which].value;
    if (selectNew.firstChild.textContent != children[which].text) {
        alert('select value has been changed');
        selectNew.firstChild.textContent = children[which].text;
    }
}

更新fiddle here

【讨论】:

  • 非常感谢!正如我所说,我现在正在盯着看,一开始很困难,但很有趣。为了避免问下一个问题,我可以使用你的 js barin 来帮助我解决下一个小问题吗?为什么这个对我不起作用?非常感谢温特维尔特!感激不尽!!! select.addEventListener('change', function() { alert('select changed'); }) 再次感谢您
  • 不客气!如果您想使用我的 JSFiddle 并更新:您可以在我提供的链接上更改任何您想要的内容(单击运行以进行测试)。但是你不能保存。如果您也想要:您可以创建自己的(免费)帐户,然后单击我的 Fiddle 中的“分叉”按钮。然后,您可以更新并保存以做任何您喜欢的事情。
  • 我相信你的帮助有多大!每当你接近英国中部时,我都欠你一杯啤酒!好了,我只是想检测一下 select 的值何时更改 jsfiddle.net/pawelgrzybek/gym4wnLu/1 Very(js 选项卡的引导)
  • 再次感谢您!
【解决方案2】:

它不会杀死你的事件,你通过设置 textContent 来删除你的选项元素,所以当你点击 div 时没有任何东西可以显示。您需要设置 div 的第一个 TextNode 的 textContent。

// Define select and options
var select = document.getElementById('select');
var children = select.children;

// Recreate select via divs and keep same class
select.style.display = 'none';
var selectNew = document.createElement('div');
selectNew.className = select.classList;
selectNew.textContent = select.children[0].text;
select.parentNode.insertBefore(selectNew, select);
selectNew.addEventListener('click', function(e) {
  toggleChildren(e);
});

function toggleChildren() {
  selectNew.classList.toggle('active');
}

// remap children
var childArray = [];
for (var i = 0; i < children.length; i++) {
  var child = document.createElement('div');
  child.innerHTML = select.children[i].text;
  child.dataset.value = select.children[i].value;
  selectNew.appendChild(child);
  childArray.push(child);

  child.addEventListener("click", function () {
    selectChoice();
  });
}

function selectChoice() {
  var which = childArray.indexOf( event.target || event.srcElement);
  select.value = children[which].value;

  //get the first textnode and set its textContent
  selectNew.childNodes[0].textContent = children[which].text;
}
.select {
  position: relative;
  width: 100%;
  line-height: 3em;
  background: #eee;
}
.select > div {
  position: absolute;
  display: none;
  width: 100%;
}
.select > div:nth-child(1) {
  top: 2em;
}
.select > div:nth-child(2) {
  top: 4em;
}
.select > div:nth-child(3) {
  top: 6em;
}
.select > div:nth-child(4) {
  top: 8em;
}
.select > div:nth-child(5) {
  top: 10em;
}
.select > div:hover {
  background: #eee;
}
.select.active > div {
  display: block;
}
<select name="sortby" id="select" class="select">
  <option value="val1">Value 1</option>
  <option value="val2">Value 2</option>
  <option value="val3">Value 3</option>
  <option value="val4">Value 4</option>
  <option value="val5">Value 5</option>
</select>

【讨论】:

  • 非常感谢!正如我所说,我现在正在盯着看,一开始很困难,但很有趣。为什么这个不工作很容易回答吗? select.addEventListener('change', function() { alert('select changed'); })再次感谢您
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-03-23
  • 1970-01-01
  • 2020-11-10
  • 2016-01-24
  • 1970-01-01
  • 1970-01-01
  • 2020-11-22
相关资源
最近更新 更多