일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- ...args
- .toLocalString()
- 1주차
- 2020년 준비
- 2주차
- 4주차
- 5주차
- array
- array method
- async
- authentication
- AWS
- codestates
- commit
- Cookie
- CSS
- Data Structre
- Data Structure
- DataSturcutre
- Date.now()
- DB에 사진 저장하기
- Dev log
- DOM
- EC2
- EC2로 웹 만드는 방법
- EC2와 S3 연결하기
- element
- Es5
- ES6
- event 객체
- Today
- Total
souvenir
20.06.22-27 코딩공부(2)_filtering 구현 본문
지난번 글에 이어 filtering 기능 구현을 하면서 겪었던 에러를 정리해보고자 한다.
filtered 함수 수도 코드
- username(div.divName)에 클릭 이벤트 주기
- 클릭 이벤트를 받은 username의 li 외에 다른 li는 지우기
- 가능하다면 GoBack 버튼을 만들어 filtering전의 모습으로 복구
1. username(div.divName)에 클릭 이벤트 주기
let cilck = document.querySelecor('.read-username').oncilck;
cilck = filtered;
//filtered()로 입력하면 클릭할 때 되는 것이 아니라 바로 함수가 실행되게 됨
click;
//밖에서 한번 실행을 해주어야 적용되기 때문에 한번 더 선언해줌.
위와같이 작성했을 때의 문제는 DATA 객체에 있는 이름들만 클릭 이벤트가 적용되고 새롭게 작성된 message의 username은 클릭되지 않았다.
1) 전역부분에서 태그를 호출했기 때문에,
2) 특정 함수를 통해 출력되는 새로운 메세지에는 cilck 이벤트가 적용되지 않은 것
이 원인이었다.
이를 위해서 따로 클릭에 대한 함수만 만들고 그 안에서 선언해주는 것도 했지만, 결국 실행을 위해 클릭 함수를 전역부분에 선언을 다시 해줘야 해서 의미가 없었다. 한참을 고민해본 다음에야 새로운 message를 출력하는 함수 내에 cilck 함수를 넣어 연결해주면, message를 출력하면서 자동으로 이벤트를 부여해주기 때문에 해결되지 않을까 생각했다.
다행이 이제서야 문제 해결.
<message 출력 함수 내부에 클릭이벤트를 연결>
function printTweet(msg){
let li = document.createElement('li');
li.className = 'read-comment';
//중략
divread.className = 'read-box'
divName.className = 'read-username'
divComment.className = 'read-it'
divDate.className = 'date'
divName.textContent = msg.user;
divComment.textContent = msg.message
divDate.textContent = msg.created_at
let parent = document.getElementById('read-container')
parent.appendChild(li);
li.appendChild(divread);
divread.appendChild(divName);
divread.appendChild(divComment);
divread.appendChild(divDate);
li.appendChild(hr);
//이렇게 message 출력하는 함수 안에서
//username(divName)이 있는 태그에 클릭 이벤트를 부여
divName.onclick = function(){
filtered();
}
}
2. 클릭 이벤트를 받은 username의 li 외에 다른 li는 지우기
1) 클릭한 div 태그의 내용을 인식하기 : event 객체 활용
클릭 이벤트를 받은 username의 li외에 다른 li를 지우기 위해서는
1) 클릭한 username의 내용을 인식해서
2) 그 내용과 동일한 username을 가진 li를 필터링
하는 작업이 먼저 필요하다.
2번의 경우 1번만 해결되면 filter 매소드를 사용하면 되기 때문에 문제가 없었지만 1번을 푸는데 정말 오랜시간이 걸렸다. '클릭한 태그' 안의 '내용'을 인식한다는 것이 쉽지 않았다. 처음 보는 addEventListener를 이용해서 클릭이벤트를 주면 내용을 인식할 때 해서 써보기도 하였지만 결과는 태그 전체를 인식하는 것 뿐이었다.
이리 저리 헤매다가 겨우 발견한 것이 event 객체
이벤트 객체는, 쉽게 말해 사용자 입력(onclick, onkeyup, onscroll) 등의 트리거에 의해 발생한 이벤트 정보가 담긴 객체를 말한다고 한다. 사용하기 위해서는 이벤트가 일어나는 곳의 변수명을 event라고만 지정하면 된다. 지난 포스트에서 타임스탬프를 만들 때, 특정 이벤트에 활용하기 위해서는 변수 이름을 event로 지정해야 한다고 적었는데 그것도 이 event 객체로 활용하기 위해서이다. event 객체는 예를들면 아래와 같이 활용할 수 있다.
<button>아메리카노</button>
<button>카페라떼</button>
let menus = document.querySelectorAll('button'); //모든 버튼을 가져옵니다.
let btnAmericano = menus[0];
let btnCaffelatte = menus[1];
btnAmericano.onclick = handleClick;
btnCaffelatte.onclick = handleClick;
function handleClick(event) {
console.log(event); //MouseEvent 내용이 출력됨
console.log(event.target); //<button> 카페라떼 </button> 형식으로 출력됨
}
event 객체는 말그대로 이벤트를 인식하는 변수가 되었다. 여기에 target이라는 부분만 더하면 이벤트가 타게팅된 내용(HTML형식)을 인식할 수 있다. 타겟팅된 내용도 DOM 형식이기 때문에 .textContent를 활용하여 태그 안의 내용을 확인할 수 있었다.
즉, event.target.textConent 라는 형식으로 클릭한 태그 안의 내용물을 인식하게 할 수 있었다.
어렵게 헤맨것에 비해 너무도 단순하게 풀렸던.....하하
2) 인식한 username과 동일한 username을 가진 li만 필터링 하기
새롭게 작성한 message도, 기존의 message도 DATA 배열에 객체로 넣어두었기 때문에 이 내용을 배열 메소드인 filter를 DATA 배열에 적용하여 쉽게 풀 수 있었다.
3) 필터링된 message 외에는 지우기
문제는 이 부분이었다.
- filtered()가 실행되면
- li 태그들은 지우고
- 필터링 된 부분(filteredDATA)만 기존에 만든 printTweet() 함수를 이용해서 출력
하고자 하였다. 문제는 li 태그들을 remove()나 .textContent =''를 해도 지워지지 않았던 것.
li 태그의 형식을 확인해 보니 HTML collection이라고 나왔다. stackover floor에서도 HTML collection이나 nodeList에서도 적용이 가능하다는 글을 보았는데 실행되지 않아서 많이 헤매다가 remove()의 MDN 문서를 정확히 보고서야 원인을 알게 되었다.
https://developer.mozilla.org/en-US/docs/Web/API/ChildNode/remove
reomove()의 예시를 보면 id 하나만 제거를 하고 있었다. 즉 요소 하나에 대해서만 적용할 수 있다는 것.
그래서 현재 내가 호출한 태그는 HTML collection, 즉 배열이기 때문에 for문을 이용해서 하나하나 적용하게끔 수정하였다.
그렇게 하여 최종적으로 수정한 filtered()함수
function filtered(){
let li = document.getElementsByClassName('read-comment');
for(let i = li.length-1; i>=0; i--){
li[i].remove()
}
let filteredDATA = //배열
DATA.filter(function(el){
if(el.user === event.target.textContent){
return true;
}return false;
});
filteredDATA.forEach(printTweet) //printTweet은 해당 내용을 message로 출력해주는 함수
return filteredDATA
}
아쉽게도 filtered() 함수 사용 후에 Go Back 버튼을 만들어 기존의 내용으로 복구할 수 있는 기능을 구현하고자 하였으나... 이것또한 filter 되었던 message 아래에 추가로 기존 message가 붙여지게 되면서 중복되게 되었다. 이것도 좀 더 고민해보면 해결할 수 있을 것 같으나 필수 요소는 아닌 것 같아 패스ㅋㅋㅋㅋ
담에 시간이 되면 다시 해결해 볼 수 있도록 해야 겠다.
'2020년 > TIL(Today I Learn)' 카테고리의 다른 글
20.07.22_회고 (0) | 2020.07.22 |
---|---|
[Pre] Pre 코스 회고 (0) | 2020.07.22 |
20.06.22-27 코딩 공부 (0) | 2020.06.30 |
20.06.20_mini 해커톤(2) (0) | 2020.06.30 |
20.06.14-15 코딩연습 (0) | 2020.06.18 |