Javascript

focusout, blur 이벤트 차이와 이해 :: 마이구미

mygumi 2018. 6. 9. 15:35
반응형

이 글은 focusout 와 blur 의 차이점을 알아보고, 이벤트 발생에 있어, 주의사항을 다뤄본다.

다음과 같은 의문 또는 버그가 발생했다면, 글이 도움이 될 것이다.

focusout 과 blur 의 차이를 알고 싶다.

focusout 또는 blur 를 사용중 다음과 같은 에러가 발생했다.


"Uncaught DOMException: Failed to execute 'remove' on 'Element': The node to be removed is no longer a child of this node. Perhaps it was moved in a 'blur' event handler?"


focusout 과 blur 의 차이


focusout 는 의미 그대로 엘리먼트가 포커스를 잃었을 때 발생되는 이벤트이다.

같은 용도로 사용되는 이벤트로 blur 가 있는 것이다.


둘 사이의 차이점은 버블링 여부이다. => 버블링은 다른 글을 참고바란다. (http://mygumi.tistory.com/315)

focusout 는 버블링이 일어나고, blur 는 버블링이 일어나지 않는다.


세트로는 {focusin - focusout} 와 {focus - blur} 로 분류된다.

다음 예제 코드를 통해 보다 쉽게 이해할 수 있을 것이다.


See the Pen focusout vs blur by leejunghyun (@mygumi) on CodePen.


위 예제의 출력값을 보면 focusout 은 자식 -> 부모 순으로 출력되는 것으로 보아 버블링을 확인할 수 있다.

blur 의 경우에는 포커스를 잃은 자식만이 출력되는 것을 확인할 수 있다.




Error => Failed to execute 'remove' on 'Element': ......


위와 같은 에러는 remove 또는 removeChild 와 같은 엘리멘트를 삭제하는 메소드를 사용할 때 주로 발생한다.

다음과 같은 시나리오를 보자.

자세한 코드는 다음 링크를 통해 확인하면 된다. => Codepen Example


  • 입력창을 만든다.
  • 생성된 입력창은 ESC 키 또는 포커스를 잃게 되면 삭제된다.


위 과정을 위해서는 keyup, blur(또는 focusout) 이벤트를 사용하면 된다.


input.addEventListener("keyup", e => { if (e.keyCode === 27) { e.target.remove(); } }); input.addEventListener("blur", e => { input.remove(); })


이와 같은 예제에서 ESC 키를 눌렀을 때, 언급했던 에러가 발생되는 것이다.

왜 발생하는 것일까?

에러를 해석하면 제거할 엘리먼트가 존재하지 않는다는 식으로 말한다.

하지만 코드를 보면 전혀 그렇게 될리가 없다고 생각된다.


이유는 엘리먼트가 제거될 때, 포커스를 잃었다는 이벤트를 발생하게 된다.

* blur 뿐만 아니라 focusout 도 이와 같이 발생된다.

이것을 그림으로 표현하면 다음과 같다.



위와 같은 흐름 때문에 제거할 엘리먼트가 존재하지 않기 때문에 에러가 발생하게 된다.

문제를 해결하기 위해서는 많은 방법이 있겠지만, 2가지를 다뤄본다.


1. 플래그 변수 활용


input.addEventListener("keyup", e => { if (e.keyCode === 27) { removed = true; // Please set it before the remove(). e.target.remove(); } }); input.addEventListener("blur", e => { if (removed) { return; } input.remove(); })


2. 다른 이벤트에 제거 위임


input.addEventListener("keyup", e => { e.target.blur(); });


keyup 이벤트에서 제거하지 않고, 바로 포커스를 잃는 이벤트를 발생시켜 제거를 위임한다.

자세한 건 예제 코드 링크를 참고하길바란다.

반응형