多个选择的一个事件处理程序
One event handler for multiple selects
我在一个页面上有多个 select,像这样:
<select id="select-1" class="action">
<option val=1>1</option>
<option val=2>2</option>
</select>
<select id="select-2">
<option val=1>1</option>
<option val=2>2</option>
</select>
<select id="select-3" class="action">
<option val=1>1</option>
<option val=2>2</option>
</select>
当 selects with class “action” 改变时,我需要用 JS 代码做一些动作。
我可以这样做:
var elements = document.getElementsByClassName("classname");
for (var i = 0; i < elements.length; i++) {
elements[i].addEventListener('click', myFunction, false);
}
但也许有更好的方法来处理这个问题。
所以我的问题是:使用一个事件处理程序处理多个 select 元素的最佳方法是什么?
另一种方法是使用 event delegation,您将 click
挂接到所有这些 select 所在的祖先元素上,并利用 click
气泡:
document.querySelector("selector-for-the-container").addEventListener("click", function(event) {
const select = event.target.closest(".action");
if (select && this.contains(select)) {
event.currentTarget = select;
return myFunction.call(select, event);
}
});
更新 currentTarget
并调用 myFunction
并将 this
设置为 select
使事件看起来像是直接附加到 select .不过,您 不必 必须这样做,或者您可以只做一个而不做另一个,这取决于您想要 myFunction
做什么。
参见 MDN:
首先:您的 html 无效:options 元素有 value 属性,没有 val,而且这个值必须有引号。
所以<option val=1>1</option>
是错误的,
并且必须是 <option value="1">1</option>
对于事件委托,您需要有一个父元素。
由于您的代码是关于 select 元素的,因此逻辑父级应该是 <form>
元素。
对于 select 年代,主要事件是更改事件,而不是点击事件
最后一点,所有表单元素都必须有一个名称,这个名称在提交表单时使用,而不是 id。
在表单中使用名称属性的另一个好处是它们可以直接用于引用表单的任何子元素
所以完整的代码是:
const myForm = document.forms['my-form']
// get any -change- event on all the form
myForm.addEventListener('change', myFunction, false)
// event delegation function
function myFunction(evt)
{
// ignore other cases:
if (!evt.target.matches('select.action')) return
console.clear()
console.log( 'change on :', evt.target.name )
console.log( 'value is', myForm[evt.target.name].value )
}
// disable form submit
myForm.onsubmit =evt=>evt.preventDefault()
<form action="" name="my-form">
<select name="select-1" class="action">
<option value="s1_1"> s1 -1 </option>
<option value="s1_2"> s1 -2 </option>
</select>
<select name="select-2">
<option value="s2_11"> s2 -1 </option>
<option value="s2_12"> s2 -2 </option>
</select>
<select name="select-3" class="action">
<option value="s3_11"> s3 -1 </option>
<option value="s3_12"> s3 -2 </option>
</select>
</form>
我在一个页面上有多个 select,像这样:
<select id="select-1" class="action">
<option val=1>1</option>
<option val=2>2</option>
</select>
<select id="select-2">
<option val=1>1</option>
<option val=2>2</option>
</select>
<select id="select-3" class="action">
<option val=1>1</option>
<option val=2>2</option>
</select>
当 selects with class “action” 改变时,我需要用 JS 代码做一些动作。
我可以这样做:
var elements = document.getElementsByClassName("classname");
for (var i = 0; i < elements.length; i++) {
elements[i].addEventListener('click', myFunction, false);
}
但也许有更好的方法来处理这个问题。
所以我的问题是:使用一个事件处理程序处理多个 select 元素的最佳方法是什么?
另一种方法是使用 event delegation,您将 click
挂接到所有这些 select 所在的祖先元素上,并利用 click
气泡:
document.querySelector("selector-for-the-container").addEventListener("click", function(event) {
const select = event.target.closest(".action");
if (select && this.contains(select)) {
event.currentTarget = select;
return myFunction.call(select, event);
}
});
更新 currentTarget
并调用 myFunction
并将 this
设置为 select
使事件看起来像是直接附加到 select .不过,您 不必 必须这样做,或者您可以只做一个而不做另一个,这取决于您想要 myFunction
做什么。
参见 MDN:
首先:您的 html 无效:options 元素有 value 属性,没有 val,而且这个值必须有引号。
所以<option val=1>1</option>
是错误的,
并且必须是 <option value="1">1</option>
对于事件委托,您需要有一个父元素。
由于您的代码是关于 select 元素的,因此逻辑父级应该是 <form>
元素。
对于 select 年代,主要事件是更改事件,而不是点击事件
最后一点,所有表单元素都必须有一个名称,这个名称在提交表单时使用,而不是 id。
在表单中使用名称属性的另一个好处是它们可以直接用于引用表单的任何子元素
所以完整的代码是:
const myForm = document.forms['my-form']
// get any -change- event on all the form
myForm.addEventListener('change', myFunction, false)
// event delegation function
function myFunction(evt)
{
// ignore other cases:
if (!evt.target.matches('select.action')) return
console.clear()
console.log( 'change on :', evt.target.name )
console.log( 'value is', myForm[evt.target.name].value )
}
// disable form submit
myForm.onsubmit =evt=>evt.preventDefault()
<form action="" name="my-form">
<select name="select-1" class="action">
<option value="s1_1"> s1 -1 </option>
<option value="s1_2"> s1 -2 </option>
</select>
<select name="select-2">
<option value="s2_11"> s2 -1 </option>
<option value="s2_12"> s2 -2 </option>
</select>
<select name="select-3" class="action">
<option value="s3_11"> s3 -1 </option>
<option value="s3_12"> s3 -2 </option>
</select>
</form>