본문으로 바로가기

Element.closest()

category JavaScript 2021. 5. 24. 13:23

See the Pen QWpMONR by unganam (@unganam) on CodePen.

위와 같이 리스트 안에 아이템 리스트가 존재하고 아이템 리스트 안에 또 버튼이 존재하는 html이 있다

여기서 버튼을 눌렸을 때 해당 엘리먼트가 삭제되게끔 이벤트를 등록하려고 한다

li 이벤트 등록의 경우

    const $ul = document.querySelector('ul')

    const liElems =[...document.querySelectorAll('.item')]

    liElems.forEach($li=>$li.addEventListener('click',e=>{
        $ul.removeChild(e.target)
    }))

페이지 내에 있는 아이템들을 모두 가져와서 배열로 만든 뒤 클릭 이벤트를 주고 클릭 이벤트가 발생하면 부모의 ul에서 해당 엘리먼트를 삭제하는 코드..

처럼 보이지만

다음과 같이 에러가 난다

ul의 자식이 아닌 노드는 삭제할 수가 없다고 하는 에러인데 우리가 이벤트를 준 것은 li태그이지만 실제로 클릭시에 이벤트가 발생하는 엘리먼트는 바로 button이기 때문

button은 ul의 자식이 아니라 삭제를 할 수가 없다

    $ul.removeChild(e.target)

    $ul.removeChild(e.target.parentElement)
    // 혹은 
    $ul.removeChild(e.target.parentNode)

로 바꿔주면 정상적으로 삭제가 된다

하지만 리스트 아이템이 추가된다면 추가되는 만큼 이벤트를 등록해주어야하고 그 갯수가 많아진다면 성능 문제 또한 생기게 된다

ul 이벤트 등록의 경우 (위임, 버블링)

    const $ul = document.querySelector('ul')

    $ul.addEventListener('click', e=>{
        $ul.removeChild(findNode(e.target,'item'))
    })

    function findNode(node, className){
        while (!node.classList.contains(className)){
            node = node.parentElement
        }
        return node
    }

함수를 생성하지 않고도 현재 요소에서 가장 가까운 상위요소를 찾는 법이 있다

Element.closest()

    const $ul = document.querySelector('ul')

    $ul.addEventListener('click', e=>{
        $ul.removeChild(e.target.closest('.item'))
    })

훨씬 간편해졌다 주의해주어야하는 부분은 노드를 querySelector 형식으로 찾는다는 것 그래서 클래스 명 앞에 .을 붙여주었다

이 코드는 문제가 있는데 선택한 노드가 ul아래엔 있지만 item의 하위요소가 아닐 경우 html문서 밖으로 노드가 나가버려서 에러가 발생한다는 것

    const $ul = document.querySelector('ul')

    $ul.addEventListener('click', e=>{
        const target = e.target.closest('.item')

        if(target) {
            $ul.removeChild(target)
            return 
        }
    })

에러처리를 해주면 된다

See the Pen wvJqpKa by unganam (@unganam) on CodePen.

'JavaScript' 카테고리의 다른 글

modal에 keydown 이벤트 추가하기 (tabindex)  (0) 2021.06.02
parentElement vs parentNode  (0) 2021.05.25
클래스 상속  (0) 2021.05.23
local/session Storage  (0) 2021.05.22
fetch API  (0) 2021.05.21