我的HTML中有一个元素列表,如下所示:
<div class='container'>
<div class="zone green"> </div>
<div class="zone red"> </div>
<div class="zone blue"> </div>
<div class="zone yellow"> </div>
<div class="zone purple"> </div>
<div class="zone brown"> </div>
<div class="zone green"> </div>
<div class="zone red"> </div>
<div class="zone blue"> </div>
<div class="zone yellow"> </div>
<div class="zone purple"> </div>
<div class="zone brown"> </div>
<script type="text/javascript" src="script.js"></script>
</div>
我试图做到这一点,以便我点击的每个元素都会将元素中的动物记录到控制台上。 这是我的尝试:
const selection = document.querySelectorAll(".zone");
selection.forEach(element => {
element.addEventListener('click', pickSelection(element))
})
function pickSelection(animal) {
console.log(animal.textContent)
}
但是当我单击任何元素时,它没有返回任何内容。 但是,一旦我将事件侦听器更改为此,它就开始工作:
selection.forEach(element => {
element.addEventListener('click', () => pickSelection(element))
})
为什么它在代码的第二个版本中工作而不是第一个版本? 在第一个版本中,我以为我是通过编写"pickSelection(element)"将元素参数传递给 pickSelect 函数的,但显然它只有在前面有"() =>"时才有效,但是这种符号有什么区别? 谢谢。
在第一个版本中,您正在执行pickSelection
函数而不是传递其引用,addEventListener
期望在触发特定事件时将函数引用作为回调。
但是由于您传递了undefined
的pickSelection
函数的返回值(因为您没有从pickSelection
返回任何内容,因此默认情况下它返回undefined
),因此它不起作用。
在第二个版本中,您实际上是将函数引用传递给addEventListner
,这是一个箭头函数语法。
通过简单地传递引用pickSelection
,以下内容也可以工作,但这次它将接收event
对象。
const selection = document.querySelectorAll(".zone");
selection.forEach(element => {
element.addEventListener('click', pickSelection)
})
function pickSelection(event) {
//getting the event object from the callback, target refers to the current element clicked.
console.log(event.target.textContent)
}
<div class='container'>
<div class="zone green"> </div>
<div class="zone red"> </div>
<div class="zone blue"> </div>
<div class="zone yellow"> </div>
<div class="zone purple"> </div>
<div class="zone brown"> </div>
<div class="zone green"> </div>
<div class="zone red"> </div>
<div class="zone blue"> </div>
<div class="zone yellow"> </div>
<div class="zone purple"> </div>
<div class="zone brown"> </div>
</div>
此行
element.addEventListener('click', pickSelection(element));
这实际上是
const temp = pickSelection(element);
element.addEventListener('click', temp);
你想要的是
element.addEventListener('click', pickSelection);
你看出区别了吗?
在此版本中
element.addEventListener('click', pickSelection(element))
您调用了该函数pickSelection
并将其传递给element
。然后传递任何pickSelection
返回element.addEventListener
你想要/需要做的是将函数本身传递给element.addEventListener
此版本工作的原因
selection.forEach(element => {
element.addEventListener('click', () => pickSelection(element))
})
是因为您要将匿名函数传递给element.addEventListener
。这些行可以翻译成这个
function anonymousFn1(element) {
function anonymousFn2() {
pickSelection(element);
}
element.addEventListener('click', anonymousFn2);
}
selection.forEach(anonymousFn1);
请注意,在功能上还有另一个区别。
在这个
element.addEventListener('click', pickSelection);
单击事件将一个 Event 对象传递给pickSelection
而在另一个事件中,当称为 anonmousFn1forEach
时创建的变量element
被"关闭"(进行了闭包),因此当调用匿名 Fn2 时,使用该变量element
。
所以要让第一个工作,你真的需要这个
function pickSelection(event) {
const element = event.target;
console.log(element.textContent);
}
例:
const selection = document.querySelectorAll(".zone");
selection.forEach(element => {
element.addEventListener('click', pickSelection);
});
function pickSelection(event) {
element = event.target;
console.log(element.textContent);
}
<div class='container'>
<div class="zone green"> </div>
<div class="zone red"> </div>
<div class="zone blue"> </div>
<div class="zone yellow"> </div>
<div class="zone purple"> </div>
<div class="zone brown"> </div>
<div class="zone green"> </div>
<div class="zone red"> </div>
<div class="zone blue"> </div>
<div class="zone yellow"> </div>
<div class="zone purple"> </div>
<div class="zone brown"> </div>
</div>
旁注:在每个元素上注册一个侦听器是一种不好的做法。请改用事件委派:
document.querySelector(`.container`).addEventListener(`click`, ({target}) => {
const el = target.closest(`.zone`);
if (el) {
console.log(el.textContent);
}
})
<div class='container'>
<div class="zone green"> </div>
<div class="zone red"> </div>
<div class="zone blue"> </div>
<div class="zone yellow"> </div>
<div class="zone purple"> </div>
<div class="zone brown"> </div>
<div class="zone green"> </div>
<div class="zone red"> </div>
<div class="zone blue"> </div>
<div class="zone yellow"> </div>
<div class="zone purple"> </div>
<div class="zone brown"> </div>
</div>