오늘은 Twittler의 filtering을 구현하는 과정에 대해 살펴보도록 하겠다.
filtering은 특정 Username을 클릭하면 해당 User가 입력한 댓글만 보여주는 기능을 말한다.
이 기능을 구현하는 과정에서 문제가 발생했고 그 문제를 해결하기 위해 "이벤트 위임(Event Delegation)"을 이용했다.
👉 기존에 출력한 데이터뿐만 아니라 동적으로 생성된 데이터에도 이벤트를 주고 싶을 때 어떻게 해야 할까?
Username 각각에 이벤트 리스너를 추가하지 않고 Username의 상위 요소인 ul 태그, #comments에 이벤트 리스너를 줘서 하위 요소에서 발생한 클릭 이벤트를 감지할 수 있게 한다.
수정 전에는 각 Username마다 클릭 이벤트를 줘서, Username을 클릭하면 해당 User가 입력한 댓글만 출력할 수 있게 코드를 짜려고 시도했다.
하지만 동적으로 생성된 요소에 일일이 이벤트 리스너를 추가하는 게 쉽지 않았고, 따라서 "이벤트 위임"이라는 방법을 이용했다.
comments.addEventListener('click', filter, false);
// li.comment의 상위 요소인 ul#comments에 이벤트 리스너를 달았다.
function filter() {
let commentsFilter = commentsArray.filter(ele =>
ele.children[0].innerHTML == event.target.innerHTML);
commentsFilter;
comments.innerHTML = '';
for(let i = 0; i < commentsFilter.length; i++) {
let filterComment = document.createElement('li');
filterComment = commentsFilter[i];
filterComment.className = 'comment';
let filterUser = document.createElement('div');
filterUser = commentsFilter[i].children[0];
filterUser.className = 'user';
let filterMsg = document.createElement('div');
filterMsg = commentsFilter[i].children[1];
filterMsg.className = 'message';
let filterDate = document.createElement('div');
filterDate = commentsFilter[i].children[2];
filterDate.className = 'date';
filterComment.appendChild(filterUser);
filterComment.appendChild(filterMsg);
filterComment.appendChild(filterDate);
comments.prepend(filterComment);
}
}
이렇게 되면 댓글을 추가할 때마다 Username에 클릭 이벤트를 다는 대신,
댓글 목록의 상위 요소인 ul#comments가 하위에서 발생한 클릭 이벤트를 감지하게 할 수 있다.
그런데 위 코드는 Username의 이벤트만 다루는 것이 아니라 댓글 목록 전체의 이벤트를 감지한다. 따라서 Username이 아닌 댓글 내용이나 날짜 또는 댓글 목록 안의 빈 공백을 클릭했을 때도 이벤트가 작동하게 된다. 이를 해결하기 위해서는 어떤 방법을 사용하면 좋을지 좀 더 고민해보는 시간을 가져야겠다😌