오늘은 JavaScript에서 querySelector와 querySelectorAll의 차이를 알아보겠다.
그리고 querySelector로 쓰여진 함수 실행을 querySelectorAll로 어떻게 바꾸어 처리해야 되는지 살펴본다.
지정된 선택자와 일치하는 도큐먼트의 첫 번째 element를 반환한다. 일치하는 요소가 없으면 null을 반환한다.
지정된 셀렉터 그룹에 일치하는 도큐먼트의 element list를 나타낸다. 즉 NodeList를 반환한다.
지정된 셀렉터가 없는 경우에는 비어있는 NodeList로 반환된다.
일단 실행한 예제를 보면서 이해하자.
click effect를 줄 요소에 id값을 넣은 상황이다.
<div class="clock">
<h1 class="title" id="clickEffect"></h1>
</div>
<form class="form">
<input type="text" placeholder="What is your name?" />
</form>
<h4 class="greetings"></h4>
<form class="toDoForm">
<input type="text" placeholder="My tasks" />
</form>
<ul class="toDoList"></ul>
<span class="js-weather"></span>
따라서 한 개의 id 값에 이벤트를 줄 것이라면 querySelector를 사용하여 실행하면 된다.
const title = document.querySelector('#clickEffect');
const CLICKED_CLASS = 'clicked';
function handleClick() {
title.classList.toggle(CLICKED_CLASS);
}
function init() {
title.addEventListener('click', handleClick);
}
init();
하지만 여러 요소에 click effect를 한꺼번에 주고 싶다면 querySelectorAll을 사용해야 한다.
만약 HTML에 그냥 id="clickEffect"를 추가해 querySelector를 실행하면
querySelector는 해당 값이 중복일 때 맨 처음에 나온 요소만 받아 실행하기 때문에 한 개만 실행되면서 끝난다. (또한 id 값을 중복으로 사용하는 것도 옳지 않다.)
따라서 우선적으로 id 값을 다르게 하여 각각의 요소에 추가해준다.
<div class="clock">
<h1 class="title" id="clickEffect1"></h1>
</div>
<form class="form">
<input type="text" placeholder="What is your name?" />
</form>
<h4 class="greetings" id="clickEffect2"></h4>
<form class="toDoForm">
<input type="text" placeholder="My tasks" />
</form>
<ul class="toDoList"></ul>
<span class="js-weather" id="clickEffect3"></span>
그 후 querySelectorAll로 바꾸어 본다.
const title = document.querySelectorAll(
'#clickEffect1, #clickEffect2, #clickEffect3'
);
const CLICKED_CLASS = 'clicked';
function handleClick() {
for (let i = 0; i < title.length; i++) {
title[i].classList.toggle(CLICKED_CLASS);
}
}
function init() {
for (let i = 0; i < title.length; i++) {
title[i].addEventListener('click', handleClick);
}
}
init();
주의할 점은 querySelector는 element 단 한개이지만, querySelectorAll의 결과는 array, 즉 배열이기 때문에 함수 실행할 때 배열을 실행시키 듯 바꿔주어야 한다는 점이다.
나는 for문으로 실행했다.
또한 다음과 같이 for of 문도 가능하다.
function handleClick() {
for (let item of title) {
item.classList.toggle(CLICKED_CLASS);
}
}
function init() {
for (let item of title) {
item.addEventListener('click', handleClick);
}
}
init();
혹은 forEach를 사용하여 배열 요소 각각에 대해 실행하도록 할 수도 있다.
function handleClick() {
title.forEach((item) => {
item.classList.toggle(CLICKED_CLASS);
});
}
function init() {
title.forEach((item) => {
item.addEventListener('click', handleClick);
});
}
init();
참고자료(는 역시 MDN)