JS30 10강의 체크박스 예제를 혼자 해봤는데 강의 본문에 나온 코드에 비해 너무 지저분하게 구현해서 몰랐던 부분들을 정리해두려 합니다.
이번 예제는 위에나온 체크박스를 쉬프트 누르고 클릭하면 그사이에 있는 것들이 전부 체크가 되도록 하는 것이었는데 아래는 내가 구현한 코드다.
const inbox = document.querySelector(".inbox");
const checkLists = inbox.children //inbox내의 children 리스트 가져오기
const checkListsArr = Array.from(checkLists); // 배열메서드 활용을 위해 배열로 변환
let firstClickedCheckboxIndex; //처음 클릭한 체크박스 저장용 변수
let shiftHold = false //쉬프트가 눌려있는지 따로 확인하는 변수
//체크박스 DOM element 각각에 이벤트 리스너를 붙이기
for (let i = 0; i < inbox.children.length; i++) {
checkLists[i].children[0].addEventListener("keydown", handleShiftDown)
checkLists[i].children[0].addEventListener("keyup", handleShiftup)
checkLists[i].children[0].addEventListener("input", handleMultiSelect)
}
//클릭했을때 체크박스 다중 선택여부
//그냥 클릭한 체크박스와 쉬프트 클릭한 체크박스의 인덱스를 가져와서 활용
function handleMultiSelect(e) {
if (shiftHold === true) {
let shiftClickedIndex = checkListsArr.indexOf(e.path[1]);
if (shiftClickedIndex - firstClickedCheckboxIndex >= 2) {
for (let i = firstClickedCheckboxIndex; i < shiftClickedIndex; i++) {
checkLists[i].children[0].checked = true;
}
} else if (shiftClickedIndex - firstClickedCheckboxIndex <= -2) {
for (let i = firstClickedCheckboxIndex; i > shiftClickedIndex; i--) {
checkLists[i].children[0].checked = true;
}
}
} else {
firstClickedCheckboxIndex = checkListsArr.indexOf(e.path[1]);
}
}
//쉬프트가 눌린상태인지 확인하는 코드
function handleShiftDown(e) {
if (e.code === 'ShiftLeft' && shiftHold === false) {
shiftHold = true;
}
}
function handleShiftup(e) {
if (e.code === 'ShiftLeft' && shiftHold === true) {
shiftHold = false;
}
}
나름대로 고민하면서 잘 구현했다고 생각했는데 아래의 강의 풀이를 보니 전혀 그렇지 않았다.
const checkboxes = document.querySelectorAll('.inbox input[type="checkbox"]');
let lastChecked;
function handleCheck(e) {
// Check if they had the shift key down
// AND check that they are checking it
let inBetween = false;
if (e.shiftKey && this.checked) {
// go ahead and do what we please
// loop over every single checkbox
checkboxes.forEach(checkbox => {
console.log(checkbox);
if (checkbox === this || checkbox === lastChecked) {
inBetween = !inBetween;
console.log('Starting to check them in between!');
}
if (inBetween) {
checkbox.checked = true;
}
});
}
lastChecked = this;
}
checkboxes.forEach(checkbox => checkbox.addEventListener('click', handleCheck));
일단 내가 놓친 부분을 정리하면
1. 마우스클릭이벤트 발생시 쉬프트키를 누르고 있는지 MouseEvent.shiftKey 로 간단하게 체크가 가능했음.
2. 반복문을 길게 늘여쓰기보다는 forEach를 썼다면 더 간결하게 표현이 가능했음.
3. 핵심로직을 처음과 끝의 체크박스 인덱스를가져와 활용하는 방식으로 구현했는데 굳이 인덱스를 활용할 필요가 없음.
4. querySelector를 사용해서 가져온 Dom element를 한번더 쪼개서 사용했는데 querySelectorAll로 한번에 가져오는게 더 간결함.
5. Margin 영역은 클릭해도 JS event 가 fire 되지 않음. (즉 box model에서 클릭으로 해당되지 않는다는 것)
JS30을 진행하면서 느끼는 내 문제점은 습관적으로 배열 전체를 순회할 때 forEach를 잘 쓰지않고 for loop으로 돌리려고 하고 dom element를 가져올때 일일히 가져와서 세부적으로 쓰려는 점인거 같다.
'TIL > HTML, CSS, JS 이것저것' 카테고리의 다른 글
JS30-Slide in on Scroll (0) | 2021.06.15 |
---|---|
JS30-Video Player (0) | 2021.06.12 |
JS30 - HTML Canvas (0) | 2021.06.02 |
JS30 - Playing with CSS Variables and JS (0) | 2021.05.30 |
JS 30 - Drum Kit (0) | 2021.05.26 |
댓글