[JavaScript] addEventListener 써보기(마우스 이벤트)


1️⃣ addEventListener()

  • 자바스크립트에서 document오브젝트를 사용하여 html의 요소에 접근을 할 수 있습니다.
const aa = document.querySelector(".hello");
  • 위처럼 hello라는 클래스를 찾아 aa에 저장해줬습니다.
  • 이제 aaaddEventListener메소드를 이용하여 여러가지 동작(event)들을 감지할 수 있습니다.
console.dir(document);
  • document의 요소들이 무엇이 있는지 콘솔출력으로 확인해 봤습니다. console_out_document

  • 위처럼 document의 요소들중 마우스관련 요소가 여러가지 존재하였습니다.
  • 그중 하나인 mouseenter의 동작(event)를 이용해보겠습니다.
aa.addEventListener("mouseenter", mouseEnterFunc);
  • 위의코드의 동작방식은 mouseenter(마우스가 안에 있으면) mouseEnterFunc을 호출합니다.

2️⃣ 같은 클래스 동시에 작동시켜보기

  • quertSelector메소드를 이용하여 해당클래스를 불러올 수 있었습니다. 하지만 같은 클래스나 아이디가 존재할 경우 가장 처음의 것만 불러올 수 있었습니다.
  • 대신에 quertSelectorAll을 이용하면 해당클래스를 모두 불러와 배열형식으로 저장할 수 있습니다.
  • 이것을 이용하여 같은 클래스를 모두 다룰 수 있는 코드를 구현해보도록 하겠습니다.

(1) addEventlistener가 호출하는 함수에 매개변수?[실패]

  • addEventlistener동작(event)을 감지하면 두번째인자로 넣어준 함수를 호출하도록 구현했습니다. 하지만 매 변수마다 호출되는 함수들이 중복되기 때문에 매개변수를 이용하여 재사용할 수 있도록 구현해봤습니다.
function mouseLeaveFunc(a) {
  a.innerText = "Hello!";
}

function handleMouseLeave(a) {
  a.innerText = "Bye!";
}

for (let i = 0; i < aa.length; i++) {
  aa[i].addEventListener("mouseenter", handleMouse(aa[i]));
  aa[i].addEventListener("mouseleave", handleMouseLeave(aa[i]));
}
  • 결론부터 말하자면 위와같은 코드는 동작하지않았습니다. 일단 제가 생각하는 방법과는 다른식으로 매개변수를 받아오는 것 같습니다.
  • 인터넷에 검색해보면 적절하게 매개변수를 사용하는 방법이 있었습니다. 대표적으로 다음의 사이트에서 마지막 경우를 보면될 것같습니다.
    생활코딩 - ddEventListener()

(2) 무식하게 반복문을 돌리기

const aa = document.querySelectorAll(".hello");

for (let i = 0; i < aa.length; i++) {
  function mouseEnterFunc() {
    aa[i].innerText = "Hello!";
  }

  function mouseLeaveFunc() {
    aa[i].innerText = "Bye!";
  }

  aa[i].addEventListener("mouseenter", mouseEnterFunc);
  aa[i].addEventListener("mouseleave", mouseLeaveFunc);
}
  • 위의 코드처럼 함수까지도 반복문에 넣었습니다.
  • 이 방법이 올바른 방법인지는 아직 모르겠습니다. (포스트를 열고있는 동안 반복문이 계속돌고 있을 것 같은 느낌..)
  • 다행히 for문안에서 console.log()를 넣어 실험해본결과 반복문포스트가 로딩된 최초 한번만 실행되었고 이벤트가 발생하여도 반복문이 다시 돌지않았습니다. C언어에서 전처리기매크로헤더파일전처리단계에서 확장해주는 방식(?)과 같지않나 생각이듭니다.

3️⃣ 결과물

  • 랜덤하게 색을 변하게하는 기능도 추가하여 다음과 같은 결과물을 만들었습니다.
  • 아직도 Javascript에서 위와 같은 코드가 어떤식으로 작동하는지 이해가 되지 않습니다. (반복문안의 함수들을 펼쳐놓는다면 함수이름이 모두 같을텐데 어떻게 적절한 변수가 들어있는 함수를 찾아서 호출할까..?)
  • 또한 javascript언어에서 css의 요소들을 다루는 것도 올바른 사용 방법인 것 같지 않습니다.
  • 하지만 Javascript이러한 놀라운 기능까지도 할 수 있다는 것을 알게되었습니다.

put your mouse here!
put your mouse here!
put your mouse here!
put your mouse here!
put your mouse here!
put your mouse here!
put your mouse here!

4️⃣ JS방식으로 깔끔하게 작성하기(21.08.24추가내용)

  • 자바스크립트를 공부하다 문득 for문으로 무식하게 작성했던때가 생각 났습니다. (위의 2번)
  • 그나마 제대로 공부했던 언어C언어였기 때문에 자바스크립트의 함수의 매개변수의 개념이 익숙하지가 않은 것이 원인이였습니다.
  • 그 중하나로 이벤트함수event요소를 받을 수 있으며 .target을 이용하여 이벤트가 일어난곳의 부모노드에 접근할 수 있습니다.
  • 아직도 이벤트 위임 등과 같은 이벤트와 관련된 것들을 더 공부해야겠지만, 일단은 위의 (2)for문안에 위치한 이벤트 함수들을 다음과 같이 밖으로 끄집어낼 수 있습니다.
const aa = document.querySelectorAll(".hello");

function mouseEnterFunc(event) {
  event.target.innerText = "Hello!";
}

function mouseLeaveFunc(event) {
  event.target.innerText = "Bye!";
}

for (let i = 0; i < aa.length; i++) {
  aa[i].addEventListener("mouseenter", mouseEnterFunc);
  aa[i].addEventListener("mouseleave", mouseLeaveFunc);
}
  • 더 나아가 foreach()메소드를 이용하면 이벤트함수들도 자바스크립트스럽게(?) 작성할 수 있습니다.
aa.forEach((a) => {
  a.addEventListener("mouseenter", mouseEnterFunc);
  a.addEventListener("mouseleave", mouseLeaveFunc);
});
  • 하지만 주의해야될 부분이 있는데 aa변수는 “querySelectorAll()”로 생성한 노드배열입니다.
  • 유사배열이라고도 할 수 있는데, 이처럼 유사배열의 경우 배열메소드를 이용할 수 없을 수도 있습니다.
  • 다행히 foreach()메소드는 노드배열의 Prototype에도 존재했기때문에 사용이 가능했습니다. nodelist_func_list

  • 배열과 유사배열에 관해 자세히 알고 싶으면 다음사이트를 참고하면 될 것 같습니다.
    👉🏻 👉🏻 👉🏻 배열과 유사배열 - ZeroCho TV
  • 이러한 유사배열Array.from()을 이용하면 배열처럼 만들 수 있습니다.
const aa = document.querySelectorAll(".hello");
console.log(aa); // NodeList(7)
console.log(Array.from(aa)); // Array(7)
  • 위의 콘솔출력결과를 보면 정상적으로 배열로 바뀐모습을 알 수 있습니다.
  • Array.from()은 단순히 배열로 바꿔주는 함수가 아니라 기존의 배열을 커스텀하여 복사된 배열을 반환하는 기능을 가지고 있습니다.
  • 유사배열을 안전하게 배열로 바꾸어 매소드에 접근하고자 한다면 다음과 같이 사용하면 됩니다.
Array.from(aa).forEach((a) => {
  a.addEventListener("mouseenter", mouseEnterFunc);
  a.addEventListener("mouseleave", mouseLeaveFunc);
});
  • 어찌됐든 노드배열 Prototype에도 forEach()메소드가 있다는 것을 안 이상 굳이 Array.from사용할 필요가 없을 것 같습니다. Array.from()기능을 사용하면 배열을 복사하는 과정이 일어나기 때문에 조금의 성능저하가 있지않을까 생각이 들기 때문입니다. (유사배열에 매소드가 존재하는지 햇갈린다면 사용하는게 좋을 것 같습니다.)




© 2021.02. by kirim

Powered by kkrim