이벤트 리스너 제거 방법에 대한 추가 옵션

이 글의 번역자는 360 Qiwu Troupe의 프론트엔드 개발 엔지니어입니다.

원제: 이벤트 리스너 제거 옵션이 있습니다.

저자: 알렉스 맥아더

원래 주소: https://www.macarthur.me/posts/options-for-removing-event-listeners


JavaScript에서 이벤트 리스너를 제거하는 일반적인 방법을 검토하세요.

런타임 시 코드를 정리하는 것은 효율적이고 예측 가능한 애플리케이션을 구축하는 데 필수적인 부분입니다. JavaScript에서는 이벤트 리스너를 적절하게 관리하고 더 이상 이벤트를 리스닝하는 데 필요하지 않은 경우 이를 제거해야 합니다.

위의 목표를 달성하는 방법에는 여러 가지가 있으며 각 방법에는 특정 상황에 더 적합하게 만드는 장단점이 있습니다. 우리는 일반적으로 사용되는 몇 가지 방법과 사용할 방법을 선택할 때 고려해야 할 몇 가지 요소를 다룰 것입니다.


단일 이벤트 리스너가 있는 버튼인 다음 코드를 실험해 보겠습니다 click.

<button id="button">Do Something</button>

<script>
document.getElementById('button').addEventListener('click', () => {
  console.log('clicked!');
});
</script>

Chrome getEventListeners() 함수를 사용하면 요소에 하나의 리스너만 연결된 것을 볼 수 있습니다.

d94d3ed5c22ca1b8f074c41222e0d0ae.png
리스너를 제거해야 하는 경우 수행 방법은 다음과 같습니다.

1. RemoveEventListener를 사용하세요.

이것은 아마도 가장 일반적인 방법이지만, 또한 당신을 지치게 할 가능성이 가장 높습니다. removeEventListener 이 메서드는 제거할 리스너 유형, 리스너의 콜백 함수, 옵션 개체 등 세 가지 매개 변수를 허용합니다.

하지만 여기에 까다로운 부분이 있습니다. 이러한 매개변수는 동일한 콜백 참조를 포함하여 리스너를 설정할 때 사용된 매개변수와 정확히 일치해야 합니다. 그렇지 않으면 removeEventListener() 작동하지 않습니다.
이를 감안할 때 다음은 완전히 유효하지 않습니다.

document.getElementById('button').addEventListener('click', () => {
  console.log('clicked!');
});

document.getElementById('button').removeEventListener('click', () => {
  console.log('clicked!');
});

리스너를 제거하기 위한 콜백은 원래 바인딩된 콜백과 완전히 동일해 보이지만 동일한 참조는 아닙니다. 이 문제에 대한 해결책은 콜백 함수를 변수로 설정하고  이를 .addEventListener() and  에서 사용하는 것입니다..removeEventListener()

const myCallback = () => {
  console.log('clicked!');
};

document.getElementById('button').addEventListener('click', myCallback);
document.getElementById('button').removeEventListener('click', myCallback);

또는 특정 시나리오의 경우 함수 내부의 함수 이름을 사용하여 리스너를 제거할 수도 있습니다.

document
  .getElementById('button')
  .addEventListener('click', function myCallback() {
    console.log('clicked!');

    this.removeEventListener('click', myCallback);
  });

이러한 제한에도 불구하고 .removeEventListener() 코드 의미가 모호하지 않다는 장점이 있습니다.

2. addEventListener의 한 번 옵션을 사용하십시오.

addEventListener() 메소드의 두 번째 객체 매개변수에는 옵션이 있습니다. once 옵션은 한 번만 사용하려는 경우 이벤트 바인딩이 자체적으로 지워지도록 설정하는 데 사용할 수 있습니다. 사용하기 매우 간단하며 다음과 같이  true설정된 경우 첫 번째 호출 후 리스너가 자동으로 제거됩니다.

const button = document.getElementById('button');

button.addEventListener('click', () => {
  console.log('clicked!');
}, { once: true });

// 'clicked!'
button.click();

// No more listeners!
getEventListeners(button) // {}

사용 사례에 적용 가능한 경우 이 접근 방식은 익명 함수에서도 작동하며 리스너는 한 번만 호출됩니다.

노드 복제 및 교체

때로는 특정 노드의 모든 활성 리스너를 알지 못하지만 모두 제거하고 싶을 수도 있습니다. 이 경우 전체 노드를 복제하고 복제된 노드로 교체하는 것이 가능합니다. .cloneNode() 메서드를 사용하면  .addEventListener() 전달된 모든 리스너가 유지되지 않아 깨끗한 노드가 됩니다.

클라이언트 측 JavaScript의 석기 시대에는 상위 노드를 쿼리하고 특정 하위 노드를 대체하여 이 작업이 수행되는 것을 볼 수 있습니다.

button.parentNode.replaceChild(button.cloneNode(true), button);

그러나 최신 브라우저에서는 다음을  .replaceWith() 사용하여 단순화할 수 있습니다.

button.replaceWith(button.cloneNode(true));

여기서 귀찮게 할 수 있는 유일한 점은 인라인 리스너가 보존된다는 것입니다. 즉,  onclick 이벤트가 계속 발생한다는 의미입니다.

<button id="button" onclick="console.log('clicked!')">
  Do Something
</button>

전반적으로 모든 종류의 수신기를 제거해야 하는 경우 이는 좋은 선택입니다. 단점은 목적이 뚜렷하지 않고, 좀 아첨한다는 점이다.

사용AbortController()

당신이 나와 같다면 아마도  AbortController fetch() 요청을 취소하는 데 사용된다는 말만 들어봤을 것입니다. 그러나 실제로는 훨씬 더 많은 사용 시나리오가 있습니다.

.addEventListener() 리스너를 명령적으로 중단/제거하는 데 사용되도록 신호를 구성할 수 있습니다. 해당 컨트롤러가 호출  .abort() 되면 리스너가 제거됩니다 .

const button = document.getElementById('button');
const controller = new AbortController();
const { signal } = controller;

button.addEventListener('click', () => console.log('clicked!'), { signal });

// Remove the listener!
controller.abort();

.removeEventListener() 위의 접근 방식은 잠재적인 취급 위험 없이 청취자를 제거하는 더 깔끔한 방법입니다  . 그리고 훨씬 더 큰 이점이 있습니다. 단일 신호와 익명 함수를 사용하여 한 번에 여러 리스너를 제거할 수 있습니다.

const button = document.getElementById('button');
const controller = new AbortController();
const { signal } = controller;

button.addEventListener('click', () => console.log('clicked!'), { signal });
window.addEventListener('resize', () => console.log('resized!'), { signal });
document.addEventListener('keyup', () => console.log('pressed!'), { signal });

// Remove all listeners at once:
controller.abort();

고려해야 할 유일한 것은 브라우저 지원입니다. 이는 비교적 새로운 기능으로, 2021년(v90)부터 Chrome에서만 완전히 지원됩니다. 따라서 몇 년 전의 브라우저 버전을 지원해야 하는 경우 이 점에 유의하세요.

43b39ae4c4086e54e4682f94168ac4c3.png

어떤 방법을 선택해야 합니까?

일반적으로 "경우에 따라"입니다. 그러나 나는 다음을 선택할 수 있습니다.

  • 콜백 함수가 변수에 할당되고 리스너가 추가된 곳에서 쉽게 액세스할 수 있는 경우 사용합니다  .removeEventListener().

  • 콜백을 한 번만 실행해야 하는 경우   의 옵션을 .addEventListener() 사용하세요  .once

  • 한 번의 작업으로 모든 리스너를 무분별하게 제거해야 하는 경우 복제 교체 방법을 사용하세요.

  • 한 번에 모두 강제로 제거하려는 리스너 체인이 있는 경우 다음을 사용하십시오. AbortController()                                 

- 끝 -

치우 극단 소개

Qi Wu Troupe는 360 그룹의 가장 큰 프런트 엔드 팀으로, 그룹을 대신하여 W3C 및 ECMA 회원(TC39)의 작업에 참여합니다. Qi Wu Troupe는 인재 교육을 매우 중시합니다. 직원이 선택할 수 있는 엔지니어, 강사, 번역가, 비즈니스 인터페이스 담당자, 팀 리더 및 기타 개발 방향이 있으며 기술 기술, 전문 기술, 일반 기술에 대한 해당 교육을 제공하여 보완합니다. 리더십 기술 등 과정. Qi Dance Troupe는 개방적이고 재능을 추구하는 태도로 Qi Dance Troupe에 관심을 갖고 합류할 수 있는 모든 종류의 뛰어난 재능을 환영합니다.

d8736d16a9c01579adfdebcc4a4e9eaf.png

추천

출처blog.csdn.net/qiwoo_weekly/article/details/132550776