event delegation(step 19)

KHW·2020년 12월 19일
0

js-study

목록 보기
1/39
post-thumbnail

1. 기본 전체 코드를 보며 이해를 시도해보자

<html><head></head><body>
  <link type="text/css" rel="stylesheet" href="https://ko.js.cx/article/event-delegation/bagua/bagua.css">


  <table id="bagua-table">
    <tbody><tr>
      <th colspan="3"><em>Bagua</em> Chart: Direction, Element, Color, Meaning</th>
    </tr>
    <tr>
      <td class="nw"><strong>Northwest</strong>
        <br>Metal
        <br>Silver
        <br>Elders
      </td>
      <td class="n"><strong>North</strong>
        <br>Water
        <br>Blue
        <br>Change
      </td>
      <td class="ne"><strong>Northeast</strong>
        <br>Earth
        <br>Yellow
        <br>Direction
      </td>
    </tr>
    <tr>
      <td class="w"><strong>West</strong>
        <br>Metal
        <br>Gold
        <br>Youth
      </td>
      <td class="c"><strong>Center</strong>
        <br>All
        <br>Purple
        <br>Harmony
      </td>
      <td class="e"><strong>East</strong>
        <br>Wood
        <br>Blue
        <br>Future
      </td>
    </tr>
    <tr>
      <td class="sw"><strong>Southwest</strong>
        <br>Earth
        <br>Brown
        <br>Tranquility
      </td>
      <td class="s"><strong>South</strong>
        <br>Fire
        <br>Orange
        <br>Fame
      </td>
      <td class="se"><strong>Southeast</strong>
        <br>Wood
        <br>Green
        <br>Romance
      </td>
    </tr>

  </tbody></table>

  <script>
    let table = document.getElementById('bagua-table');

    let selectedTd;

    table.onclick = function(event) {
      let target = event.target;
      while (target != this) {
        if (target.tagName == 'TD') {
          highlight(target);
          return;
        }

        target = target.parentNode;
      }
    }

    function highlight(node) {
      if (selectedTd) {
        selectedTd.classList.remove('highlight');
      }
      selectedTd = node;
      selectedTd.classList.add('highlight');
    }
  </script>



</body></html>

브라우저에는 아래와 같은 그림으로 나타난다.

1) 표에서 Northwest North Northeast와 같은 표의 위에 있는 내용을 클릭시 일어나는 상황

event.target은

<strong>​Northwest​</strong>

this는

<table id="bagua-table">...</table>

위의 두 값을 다르므로 while문을 진행하며 target.tagName은 strong이므로 if문을 실행하지않고 target은 부모노드인

<td class ...> ... </td>

이것으로 바뀐다.

다시 while문을 진행하여 if문이 true이므로
실행되어 highlight 함수를 실행하고 기존의 selectedTd가 있다면 class에서 highlight를 삭제하고 새로운 노드를 selectedTd에 넣어준 후
해당 class에 highlight를 넣어줌으로써 강조를 나타내게 한다.

2) 1번과 외의 table 내용을 클릭할 경우

event.target은

<td class ...> ... </td>

this는

<table id="bagua-table">...</table>

이를 통해 while문이 실행되고 if문은 target의 tagName이 TD와 같으므로 while문을 반복하지않고
highlight함수를 실행하고 return 한다.

While문을 사용하는 이유

event.target의 경우 그에 해당하는 자식태그(ex Strong tag)가 선택될수가 있는데 원하는 부모태그를 확인하고 이를 변화시키기 위해서는 event.target을 기준으로 반복하며 부모태그를 찾아가서 찾아낸 부모태그를 원하는 변환을 진행시키게 하는 것이 필요하기때문이다.

실행결과

왼쪽 위의 테이블을 클릭하면 아래와같이 빨간색으로 전과는 다르게 highlight 되는것을 볼 수 있다.


2. data-action

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style>
</style>
</head>
<body>
<article
  id="electriccars"
  data-columns="3"
  data-index-number="12314"
  data-index-col='1bcd'
  data-parent="cars">
</article>
  <script>
var article = document.getElementById('electriccars');

console.log(article.dataset.columns) // "3"
console.log(article.dataset.indexNumber) // "12314"
console.log(article.dataset.parent) // "cars"
console.log(article.dataset.indexCol) // "1bcd"
</script>
</body>
</html>

어떤 태그에 해당하는 id를 가진 Dom을 javascript 에서 data관련 값을 얻어 낼 수 있는데 data-abc 내용의 경우 DOM.dataset.abc 형태로 접근이 가능하고 data-index-abc의 경우 DOM.dataset.indexAbc 형태로 접근이 가능하다(index 뒤에 대문자형태)


3. Bind란?

<script>
function say(something){console.log( "hi "+this.name+"."+something);};
var person = {name:"kim"};
say.bind(person);
say('how are you');
</script>

해당 내용을 실행하면
hi kim.how are you
형태로 나타난다.

bind의 주요목적은 함수와 객체를 묶는 것이다.

say라는 함수에 person이라는 객체를 묶어서 처리하고 해당 내용을 console.log한다.
이를 조금 더 복잡하게 만들면

<script>
function say(something){console.log( "hi "+this.name+"."+something);};
var person = {name:"kim"};
var g = say.bind(person);
g('how are you');
</script>

이렇게 된다.


4. 이벤트 위임 활용하기

<html><head></head><body>
  <link type="text/css" rel="stylesheet" href="https://ko.js.cx/article/event-delegation/bagua/bagua.css">

<div id="menu">
  <button data-action="save">저장하기</button>
  <button data-action="load">불러오기</button>
  <button data-action="search">검색하기</button>
</div>

<script>
  class Menu {
    constructor(elem) {
      elem.onclick = this.onClick.bind(this); // (*)
    }


    save() {
      alert('저장하기');
    }

    load() {
      alert('불러오기');
    }

    search() {
      alert('검색하기');
    }

    onClick(event) {
      let action = event.target.dataset.action;
      console.log(action);
      console.log(event.target);
      console.log(this[action]);
      if (action) {
        this[action]();
      }
    };
  }

  new Menu(menu);
</script>



</body></html>

기본적인 내용을 보면 constructor부분은 elem으로 menu를 가져오는데
실제 elem의 내용은

`<div id="menu">
  <button data-action="save">저장하기</button>
  <button data-action="load">불러오기</button>
  <button data-action="search">검색하기</button>
</div>

이부분이다.

그리고 현재 Menu안에서의 this는 Menu 자체를 나타내는중이다.

즉, elem.onclick = this.onClick.bind(this); 내용을 통해 해당 내용에 관한 클릭이 발생할 경우 Menu에 해당하는 내용(this)을 bind한 onClick함수가 실행을 한다. (이때 그냥 onClick이 아닌 this.onClick으로 사용하는 이유는 onClick함수보다 위에 있기 때문에 이를 찾을 수 있게 this를 추가한다.)

그 후 클릭이 발생한다면 onClick함수를 실행시켜서 얻은 action은 해당 data-set의 내용이므로 if문을 통과시켜 this[action]은 해당 함수를 나타내기 때문에

this[action]()

은 해당함수를 실행시키는 역할을 수행한다.

ex) this[action]이 save함수 자체라면

this[action]()

위의 내용은 save() 이므로 save함수를 실행한다.

● 해당 내용의 장점
1. 버튼마다 핸들러를 할당해주는 코드를 작성할 필요가 없어집니다. 메서드를 만들고 HTML에 그 메서드를 써주기만 하면 됩니다.
2. 언제든지 버튼을 추가하고 제거할 수 있어 HTML 구조가 유연해집니다

5. 정리

이벤트 위임을 통해 필요한 부분까지 다시 도달하여 사용하는 사용법을 좀더 다룰수있어야겠고 이를 위해서 bind와 this와 같은 내용을 다루어야 하고 data-set이라는 새로운 개념을 알게되었다.

profile
나의 하루를 가능한 기억하고 즐기고 후회하지말자

5개의 댓글

comment-user-thumbnail
2020년 12월 23일

코드를 보면서 이해해 보려는 자세가 좋았습니다.
this 와 dataset 에 관해서는
https://ko.javascript.info/dom-attributes-and-properties#ref-439
https://ko.javascript.info/object-methods
https://ko.javascript.info/bind
https://ko.javascript.info/constructor-new
https://ko.javascript.info/arrow-functions

여기 읽어보시는거 꼭 추천드립니다

2개의 답글
comment-user-thumbnail
2020년 12월 23일

잘 읽었습니다. 원래 링크의 코드를 바탕으로 설명을 풀어써주셔서 이해하는데 도움이 많이 됐어요!

1개의 답글