코딩쌀롱

Mission5 문제해결정리(bind, event delegation, template tag) 본문

개발공부

Mission5 문제해결정리(bind, event delegation, template tag)

이브✱ 2020. 12. 16. 19:49

📌 bind()

문제 발생

let view = new View();
view.addButton.addEventListener("click", view.addList);

클래스의 view.addList 함수 본체에 this는 view 객체를 가리키는데,
addEventListener에서 this는 이벤트 target이 되는 element 객체를 가리킨다.
이런 차이로 정상적으로 동작하지 않는 문제가 발생했다.

해결 방법

let view = new View();
view.addButton.addEventListener("click", view.addList.bind(view));

bind()메서드로 this가 가리키는 객체를 직접 지정해줘서 해결했다.

 

📌 Event Delegation

문제 발생

// class View의 constructor에서 속성으로 DOM 참조
    this.removeButtons = document.getElementsByClassName('remove');
// 반복문으로 removeButtons에 이벤트핸들러 연결
for(let remove of view.removeButtons) {
    remove.addEventListener("click", view.removeListItem);
}

처음 js파일이 로드될 때 removeButtons에만 반복문이 돌아가기 때문에, 동적으로 요소가 추가되는 경우, 추가된 removeButton에 반복문이 돌아가지 않아 이벤트핸들러 연결이 안 되는 문제가 발생했다.

해결 방법

이벤트 위임(Event Delegation)은 다수의 자식 요소에 각각 이벤트 핸들러를 바인딩하는 대신 하나의 부모 요소에 이벤트 핸들러를 바인딩하는 방법이다. DOM 트리에 새로운 요소를 추가하더라도 이벤트 처리는 부모 요소에 위임되었기 때문에 새로운 요소에 이벤트 핸들러를 다시 바인딩할 필요가 없다.

이는 이벤트가 이벤트 흐름에 의해, 이벤트를 발생시킨 요소의 부모 요소에도 영향(버블링)을 미치기 때문에 가능한 것이다. 실제로 이벤트를 발생시킨 요소를 알아내기 위해서는 Event.target을 사용한다.

view.list.addEventListener("click", function(e) {
    let eventTarget = e.target;
    if(eventTarget.nodeName === 'LABEL') { view.makeLineThrough(eventTarget); }
    if(eventTarget.nodeName === 'I') { view.removeListItem(eventTarget); }
});

 

📌 HTML <template>

문제 발생

createElement, createTextNode로 일일이 HTML을 JS로 추가하기가 번거로워서 다른 방법을 찾아보았다.

해결 방법

HTML의 <template>이 내가 생각하던, 원하던 것을 그대로 해준다는 것을 찾을 수 있었다.

createListItem (value) {
        const template = document.getElementById('template');
        const copy = template.content.cloneNode(true);
        const node = document.createTextNode(value);
        copy.querySelector('span').appendChild(node);
        this.list.appendChild(copy);
    }

HTML <template> 태그는 추가되거나 복사될 수 있는 HTML 요소들을 정의할 때 사용한다. <template> 요소 내의 콘텐츠는 페이지가 로드될 때 즉시 렌더링되지 않으며, 사용자에게는 보이지 않는다. 하지만 나중에 자바스크립트를 사용하여, 해당 콘텐츠를 복제한 후 보이도록 렌더링할 수 있다.

<template> 요소는 특정 HTML 요소들을 원하지 않을 때까지 계속해서 다시 사용할 수 있게 해준다.

 

Comments