如何分配动态 children 一个点击事件侦听器?
How to assign dynamic children a click event listener?
我有一个包含许多元素的 parent 容器,它不是一个明确定义的元素数量,它是在用户开始在输入字段中输入内容时使用 API 生成的。这些元素也是 parents 到其他元素。 (下面我会举个例子)
我的想法是,一旦用户单击该元素,我想显示一个叠加层,其中包含有关该特定元素的更多信息。听起来不错,但到目前为止我尝试过的方法都没有用。
我试图在容器上添加一个事件侦听器。考虑这个基本的 HTML 模板。
<ul>
<li><span>Item 1</span><span>X</span></li>
<li><span>Item 2</span><span>X</span></li>
<li><span>Item 3</span><span>X</span></li>
<li><span>Item 4</span><span>X</span></li>
</ul>
<form>
<input type="text" id="test">
</form>
所以这里我们有一个 UL,它是 parent 元素,LI 是它的 children。但是,LI 也是 parents 到 span 标签,这些标签应该显示一些重要信息,所以我不能删除这些标签。
输入字段在这里只是动态地添加一些东西,模仿我的 API 的工作方式。
就像我说的,我尝试在 UL 上添加一个事件侦听器 parent >>
const items = ul.querySelectorAll('li');
items.forEach(item => item.addEventListener('click', function(e) {
console.log(this);
}));
});
});
然后我尝试为每个项目添加一个事件侦听器,但不是在我单击它们时一次记录一个项目,而是记录一个、两个、三个等等。
我觉得我在这里遗漏了一些东西,我不知道它是什么。你们能帮帮我吗?
稍后编辑:我找到了这个解决方案,但它对我来说似乎不是很优雅,如果我稍后更改内容(比如添加更多 children等)。
ul.addEventListener('click', e => {
const items = ul.querySelectorAll('li');
if(e.target.tagName === 'LI' || e.target.parentElement.tagName === 'LI') {
if(e.target.tagName === 'LI') {
e.target.remove();
} else if(e.target.parentElement.tagName === 'LI') {
e.target.parentElement.remove();
}
}
});
您可以使用函数 Element.closest() 查找父元素。
const ul = document.querySelector('ul');
ul.addEventListener('click', e => {
let li = e.target.closest('LI');
li.remove();
});
document.forms.newitem.addEventListener('submit', e => {
e.preventDefault();
let newitem = document.createElement('LI');
newitem.innerText = e.target.test.value;
ul.appendChild(newitem);
});
<ul>
<li><span>Item 1</span><span>X</span></li>
<li><span>Item 2</span><span>X</span></li>
<li><span>Item 3</span><span><em>X</em></span></li>
<li>Item 4 X</li>
</ul>
<form name="newitem">
<input type="text" name="test">
</form>
每次单击一行时都会收到所有行事件的原因是您在 ul
元素中添加了一个单击事件,而您只需要在 li
元素
您喜欢的方式非常相似:
let ul = document.querySelector("ul");
const items = ul.querySelectorAll("li");
items.forEach((item) =>
item.addEventListener("click", function (e) {
let getTargetRow = e.target.parentElement;
if (getTargetRow.nodeName === "LI"){
console.log("the line removed:",getTargetRow.textContent);
getTargetRow.remove();
}
})
);
<ul>
<li><span>Item 1</span><span>X</span></li>
<li><span>Item 2</span><span>X</span></li>
<li><span>Item 3</span><span>X</span></li>
<li><span>Item 4</span><span>X</span></li>
</ul>
<form>
<input type="text" id="test" />
</form>
我有一个包含许多元素的 parent 容器,它不是一个明确定义的元素数量,它是在用户开始在输入字段中输入内容时使用 API 生成的。这些元素也是 parents 到其他元素。 (下面我会举个例子)
我的想法是,一旦用户单击该元素,我想显示一个叠加层,其中包含有关该特定元素的更多信息。听起来不错,但到目前为止我尝试过的方法都没有用。
我试图在容器上添加一个事件侦听器。考虑这个基本的 HTML 模板。
<ul>
<li><span>Item 1</span><span>X</span></li>
<li><span>Item 2</span><span>X</span></li>
<li><span>Item 3</span><span>X</span></li>
<li><span>Item 4</span><span>X</span></li>
</ul>
<form>
<input type="text" id="test">
</form>
所以这里我们有一个 UL,它是 parent 元素,LI 是它的 children。但是,LI 也是 parents 到 span 标签,这些标签应该显示一些重要信息,所以我不能删除这些标签。 输入字段在这里只是动态地添加一些东西,模仿我的 API 的工作方式。
就像我说的,我尝试在 UL 上添加一个事件侦听器 parent >>
const items = ul.querySelectorAll('li');
items.forEach(item => item.addEventListener('click', function(e) {
console.log(this);
}));
});
});
然后我尝试为每个项目添加一个事件侦听器,但不是在我单击它们时一次记录一个项目,而是记录一个、两个、三个等等。 我觉得我在这里遗漏了一些东西,我不知道它是什么。你们能帮帮我吗?
稍后编辑:我找到了这个解决方案,但它对我来说似乎不是很优雅,如果我稍后更改内容(比如添加更多 children等)。
ul.addEventListener('click', e => {
const items = ul.querySelectorAll('li');
if(e.target.tagName === 'LI' || e.target.parentElement.tagName === 'LI') {
if(e.target.tagName === 'LI') {
e.target.remove();
} else if(e.target.parentElement.tagName === 'LI') {
e.target.parentElement.remove();
}
}
});
您可以使用函数 Element.closest() 查找父元素。
const ul = document.querySelector('ul');
ul.addEventListener('click', e => {
let li = e.target.closest('LI');
li.remove();
});
document.forms.newitem.addEventListener('submit', e => {
e.preventDefault();
let newitem = document.createElement('LI');
newitem.innerText = e.target.test.value;
ul.appendChild(newitem);
});
<ul>
<li><span>Item 1</span><span>X</span></li>
<li><span>Item 2</span><span>X</span></li>
<li><span>Item 3</span><span><em>X</em></span></li>
<li>Item 4 X</li>
</ul>
<form name="newitem">
<input type="text" name="test">
</form>
每次单击一行时都会收到所有行事件的原因是您在 ul
元素中添加了一个单击事件,而您只需要在 li
元素
您喜欢的方式非常相似:
let ul = document.querySelector("ul");
const items = ul.querySelectorAll("li");
items.forEach((item) =>
item.addEventListener("click", function (e) {
let getTargetRow = e.target.parentElement;
if (getTargetRow.nodeName === "LI"){
console.log("the line removed:",getTargetRow.textContent);
getTargetRow.remove();
}
})
);
<ul>
<li><span>Item 1</span><span>X</span></li>
<li><span>Item 2</span><span>X</span></li>
<li><span>Item 3</span><span>X</span></li>
<li><span>Item 4</span><span>X</span></li>
</ul>
<form>
<input type="text" id="test" />
</form>