질문 : div와 같은 객체의 모든 이벤트를 완전히 제거 할 수있는 방법이 있습니까?
편집 : div.addEventListener('click',eventReturner(),false);
이벤트 별로 추가 하고 있습니다.
function eventReturner() {
return function() {
dosomething();
};
}
EDIT2 : 작동하지만 내 경우에 사용할 수없는 방법을 찾았습니다.
var returnedFunction;
function addit() {
var div = document.getElementById('div');
returnedFunction = eventReturner();
div.addEventListener('click',returnedFunction,false); //You HAVE to take here a var and not the direct call to eventReturner(), because the function address must be the same, and it would change, if the function was called again.
}
function removeit() {
var div = document.getElementById('div');
div.removeEventListener('click',returnedFunction,false);
}
답변
모든 이벤트 제거가 무슨 뜻인지 잘 모르겠습니다 . 특정 유형의 이벤트에 대한 모든 처리기를 제거하거나 한 유형에 대한 모든 이벤트 처리기를 제거 하시겠습니까?
모든 이벤트 핸들러 제거
모든 이벤트 핸들러 (모든 유형)를 제거 하려면 요소를 복제 하고 복제로 바꿀 수 있습니다.
var clone = element.cloneNode(true);
참고 : 이렇게하면 속성과 자식이 유지되지만 DOM 속성에 대한 변경 사항은 유지되지 않습니다.
특정 유형의 “익명”이벤트 핸들러 제거
다른 방법은 사용하는 removeEventListener()
것이지만 이미 시도했지만 작동하지 않은 것 같습니다. 여기에 캐치가 있습니다 .
addEventListener
익명 함수를 호출 하면 매번 새 리스너가 생성됩니다.removeEventListener
익명 함수를 호출해도 효과가 없습니다 . 익명 함수는 호출 될 때마다 고유 한 객체를 생성하지만 기존 객체에 대한 참조는 아니지만 호출 할 수 있습니다. 이러한 방식으로 이벤트 리스너를 추가 할 때는 한 번만 추가해야합니다. 추가 된 객체가 제거 될 때까지 영구적 (제거 할 수 없음)입니다.
기본적으로 익명 함수를 addEventListener
로 전달하여 함수를 eventReturner
반환합니다.
이 문제를 해결할 수있는 두 가지 가능성이 있습니다.
-
함수를 반환하는 함수를 사용하지 마십시오. 함수를 직접 사용하십시오.
function handler() { dosomething(); } div.addEventListener('click',handler,false);
-
addEventListener
반환 된 함수에 대한 참조를 저장 하는 래퍼를 만들고 이상한removeAllEvents
함수를 만듭니다 .var _eventHandlers = {}; // somewhere global const addListener = (node, event, handler, capture = false) => { if (!(event in _eventHandlers)) { _eventHandlers[event] = [] } // here we track the events and their nodes (note that we cannot // use node as Object keys, as they'd get coerced into a string _eventHandlers[event].push({ node: node, handler: handler, capture: capture }) node.addEventListener(event, handler, capture) } const removeAllListeners = (targetNode, event) => { // remove listeners from the matching nodes _eventHandlers[event] .filter(({ node }) => node === targetNode) .forEach(({ node, handler, capture }) => node.removeEventListener(event, handler, capture)) // update _eventHandlers global _eventHandlers[event] = _eventHandlers[event].filter( ({ node }) => node !== targetNode, ) }
그리고 다음과 함께 사용할 수 있습니다.
addListener(div, 'click', eventReturner(), false) // and later removeAllListeners(div, 'click')
참고 : 코드가 오랫동안 실행되고 많은 요소를 만들고 제거하는 _eventHandlers
경우 제거 할 때 포함 된 요소를 제거해야 합니다.
답변
이렇게하면 자식에서 모든 리스너가 제거되지만 큰 페이지의 경우 속도가 느려집니다. 작성하기 매우 간단합니다.
element.outerHTML = element.outerHTML;
답변
이벤트 리스너의 자체 기능을 사용합니다 remove()
. 예를 들면 :
getEventListeners().click.forEach((e)=>{e.remove()})
답변
corwin.amber가 말했듯이 Webkit과 다른 웹킷 사이에는 차이점이 있습니다.
Chrome에서 :
getEventListeners(document);
기존의 모든 이벤트 리스너가있는 객체를 제공합니다.
Object
click: Array[1]
closePopups: Array[1]
keyup: Array[1]
mouseout: Array[1]
mouseover: Array[1]
...
여기에서 제거하려는 리스너에 도달 할 수 있습니다.
getEventListeners(document).copy[0].remove();
따라서 모든 이벤트 리스너 :
for(var eventType in getEventListeners(document)) {
getEventListeners(document)[eventType].forEach(
function(o) { o.remove(); }
)
}
Firefox에서
제거 기능이없는 리스너 래퍼를 사용하기 때문에 약간 다릅니다. 제거하려는 리스너를 가져와야합니다.
document.removeEventListener("copy", getEventListeners(document).copy[0].listener)
모든 이벤트 리스너 :
for(var eventType in getEventListeners(document)) {
getEventListeners(document)[eventType].forEach(
function(o) { document.removeEventListener(eventType, o.listener) }
)
}
나는 뉴스 웹 사이트의 성가신 복사 방지를 비활성화하려는이 게시물을 우연히 발견했습니다.
즐겨!
답변
에 대한 모든 호출을 가로채는 후크 함수를 추가 할 수 있습니다 addEventHandler
. 후크는 정리에 사용할 수있는 목록으로 핸들러를 푸시합니다. 예를 들면
if (EventTarget.prototype.original_addEventListener == null) {
EventTarget.prototype.original_addEventListener = EventTarget.prototype.addEventListener;
function addEventListener_hook(typ, fn, opt) {
console.log('--- add event listener',this.nodeName,typ);
this.all_handlers = this.all_handlers || [];
this.all_handlers.push({typ,fn,opt});
this.original_addEventListener(typ, fn, opt);
}
EventTarget.prototype.addEventListener = addEventListener_hook;
}
이 코드를 기본 웹 페이지 상단 근처에 삽입해야합니다 (예 🙂 index.html
. 정리하는 동안 all_handler를 통해 루프를 수행하고 각각에 대해 removeEventHandler를 호출 할 수 있습니다. 동일한 함수로 removeEventHandler를 여러 번 호출하는 것에 대해 걱정하지 마십시오. 무해합니다.
예를 들면
function cleanup(elem) {
for (let t in elem) if (t.startsWith('on') && elem[t] != null) {
elem[t] = null;
console.log('cleanup removed listener from '+elem.nodeName,t);
}
for (let t of elem.all_handlers || []) {
elem.removeEventListener(t.typ, t.fn, t.opt);
console.log('cleanup removed listener from '+elem.nodeName,t.typ);
}
}
참고 : IE의 경우 EventTarget 대신 Element를 사용하고 =>를 기능 및 기타 여러 가지로 변경하십시오.
답변
답변을 완성하기 위해 다음은 웹 사이트를 방문하고 생성 된 HTML 및 JavaScript 코드를 제어 할 수 없을 때 이벤트를 제거하는 실제 사례입니다.
일부 성가신 웹 사이트는 로그인 양식에 사용자 이름을 복사하여 붙여 넣는 것을 방해하며, onpaste
이벤트가 onpaste="return false"
HTML 속성 으로 추가 된 경우 쉽게 우회 할 수 있습니다 . 이 경우 입력 필드를 마우스 오른쪽 버튼으로 클릭하고 Firefox와 같은 브라우저에서 “요소 검사”를 선택하고 HTML 속성을 제거하면됩니다.
그러나 이벤트가 다음과 같이 JavaScript를 통해 추가 된 경우 :
document.getElementById("lyca_login_mobile_no").onpaste = function(){return false};
JavaScript를 통해서도 이벤트를 제거해야합니다.
document.getElementById("lyca_login_mobile_no").onpaste = null;
내 예에서는 방문한 웹 사이트에서 사용하는 텍스트 입력 ID이므로 ID “lyca_login_mobile_no”를 사용했습니다.
이벤트를 제거하는 또 다른 방법 (모든 이벤트도 제거됨)은으로 제거 addEventListener
할 수없는 익명 함수를 사용하여 이벤트를 추가하는 데 사용 된 경우 수행해야하는 것처럼 노드를 제거하고 새 노드를 만드는 것 입니다 removeEventListener
. 요소를 검사하고, HTML 코드를 복사하고, HTML 코드를 제거한 다음 동일한 위치에 HTML 코드를 붙여 넣어 브라우저 콘솔을 통해이 작업을 수행 할 수도 있습니다.
또한 JavaScript를 통해 더 빠르고 자동화 될 수 있습니다.
var oldNode = document.getElementById("lyca_login_mobile_no");
var newNode = oldNode.cloneNode(true);
oldNode.parentNode.insertBefore(newNode, oldNode);
oldNode.parentNode.removeChild(oldNode);
업데이트 : Angular와 같은 JavaScript 프레임 워크를 사용하여 웹 앱을 만든 경우 이전 솔루션이 작동하지 않거나 앱이 중단되는 것으로 보입니다. 붙여 넣기를 허용하는 또 다른 해결 방법은 JavaScript를 통해 값을 설정하는 것입니다.
document.getElementById("lyca_login_mobile_no").value = "username";
현재로서는 Angular와 같이 JavaScript로 작성된 앱을 완전히 중단하지 않고 모든 양식 유효성 검사 및 제한 이벤트를 제거 할 수있는 방법이 있는지 모르겠습니다.
답변
angular에는이 문제에 대한 polyfill이 있습니다. 나는 많이 이해하지 못했지만 도움이 될 수 있습니다.
const REMOVE_ALL_LISTENERS_EVENT_LISTENER = ‘모든 리스너 제거’;
proto[REMOVE_ALL_LISTENERS_EVENT_LISTENER] = function () {
const target = this || _global;
const eventName = arguments[0];
if (!eventName) {
const keys = Object.keys(target);
for (let i = 0; i < keys.length; i++) {
const prop = keys[i];
const match = EVENT_NAME_SYMBOL_REGX.exec(prop);
let evtName = match && match[1];
// in nodejs EventEmitter, removeListener event is
// used for monitoring the removeListener call,
// so just keep removeListener eventListener until
// all other eventListeners are removed
if (evtName && evtName !== 'removeListener') {
this[REMOVE_ALL_LISTENERS_EVENT_LISTENER].call(this, evtName);
}
}
// remove removeListener listener finally
this[REMOVE_ALL_LISTENERS_EVENT_LISTENER].call(this, 'removeListener');
}
else {
const symbolEventNames = zoneSymbolEventNames$1[eventName];
if (symbolEventNames) {
const symbolEventName = symbolEventNames[FALSE_STR];
const symbolCaptureEventName = symbolEventNames[TRUE_STR];
const tasks = target[symbolEventName];
const captureTasks = target[symbolCaptureEventName];
if (tasks) {
const removeTasks = tasks.slice();
for (let i = 0; i < removeTasks.length; i++) {
const task = removeTasks[i];
let delegate = task.originalDelegate ? task.originalDelegate : task.callback;
this[REMOVE_EVENT_LISTENER].call(this, eventName, delegate, task.options);
}
}
if (captureTasks) {
const removeTasks = captureTasks.slice();
for (let i = 0; i < removeTasks.length; i++) {
const task = removeTasks[i];
let delegate = task.originalDelegate ? task.originalDelegate : task.callback;
this[REMOVE_EVENT_LISTENER].call(this, eventName, delegate, task.options);
}
}
}
}
if (returnTarget) {
return this;
}
};
….
