상황
현재 총 project
는 8개다. 이 프로젝트를 아래의 3개 종류로 분류할 수 있다.
종류별로 볼 수 있게 버튼이 위에 만들어져 있으므로, 버튼을 눌렀을 때 알맞은 프로젝트가 나오도록 만들어보자.
순서를 생각해보자
invisible
속성을 만들어서 우리가 원하는 프로젝트가 아니라면 이 속성을 추가해서 css 로 볼 수 없게 만들자.(display: none
)
필터링 버튼을 누른다
필터링 버튼의 html
요소에는 data
속성이 존재하고, 이 속성의 값으로 우리가 원하는 project
을 찾을 수 있게 만든다.
이후에는 모든 project
를 대상으로 순회를 돌면서 우리가 선택한 프로젝트인지를 검사한다.
우리가 원하는 프로젝트가 아니라면 invisible
속성을 추가해주자.
해결
기본 로직
우리의 index.html
을 보자
<div class="work__categories">
<button class="category__btn" data-filter="all">
All <span class="category__count">8</span>
</button>
<button class="category__btn" data-filter="front">
Front <span class="category__count">3</span>
</button>
<button class="category__btn" data-filter="back">
Back <span class="category__count">3</span>
</button>
<button class="category__btn" data-filter="mobile">
Mobile <span class="category__count">2</span>
</button>
</div>
여기서 버튼을 누르면 data-filter
값을 통해서 all
, front
등을 가져와서 아래의 project
에서 data-type
과 비교해서 필터링 한다.
<div class="work__projects">
<a href="www.naver.com" class="project" target="blank" data-type="front">
<img src="imgs/projects/project1.png" class="project__img" alt="" />
<div class="project__description">
<h3>Project 1</h3>
<span>first</span>
</div>
</a>
...
</div>
버튼을 눌러서 filter 값을 얻어오면 projects 를 순회하면서 invisible
속성을 넣어주면 끝!
const targetProject = target.dataset.filter;
projects.forEach(project => {
if (targetProject == 'all' || project.dataset.type == targetProject) {
project.classList.remove('invisible');
} else {
project.classList.add('invisible');
}
});
예기치 못한 문제!!!
문제는 버튼을 눌렀을 때 button
내부에 존재하는 span
을 누를 때 발생한다. 즉, 자식 요소를 클릭 했을 때 JS
에서 처리하는 부분이 문제였던것.
이 문제는 모던 자바스크립트 듀토리얼 에서 아주 멋들어지게 해결해준다. 링크의 예시에서 사용한 방법을 보면 아래와 같다.
table.onclick = function(event) {
let td = event.target.closest('td'); // (1)
if (!td) return; // (2)
if (!table.contains(td)) return; // (3)
highlight(td); // (4)
};
여기서 사용한 closest
는 요소 자신을 포함해서 부모로 올라가면서 인자로 들어온 요소에 해당하는 요소가 있으면 return 하는 메서드다. 즉, 자기 자신이 td 면 바로 자기자신을 리턴하고 아니라면 부모를 통해서 찾아가는것
이걸 우리의 코드에 접목해보면 아래처럼 된다.
workCategory.addEventListener('click', (event) => {
let target = event.target.closest('.category__btn');
if (!target) {
return;
}
...
});
이제 span
을 고의로 눌러도 부모를 찾아가면서 button 을 찾고 리턴한다!!