Hanya pertanyaan: Apakah ada cara untuk menghapus semua kejadian dari suatu objek, misalnya div?
EDIT: Saya menambahkan per div.addEventListener('click',eventReturner(),false);
acara.
function eventReturner() {
return function() {
dosomething();
};
}
EDIT2: Saya menemukan cara, yang berfungsi, tetapi tidak mungkin digunakan untuk kasus saya:
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);
}
javascript
events
dom
Florian Müller
sumber
sumber
div.onclick=null
. Tentu saja Anda tidak boleh menggunakanaddEventListener
dalam kasus ini sama sekali karena itu akan menambahkan pendengar terpisah yang berbeda dari yang ada dionclick
.Jawaban:
Saya tidak yakin apa yang Anda maksud dengan menghapus semua acara . Hapus semua penangan untuk jenis acara tertentu atau semua penangan acara untuk satu jenis?
Hapus semua penangan acara
Jika Anda ingin menghapus semua penangan kejadian (jenis apa pun), Anda dapat menggandakan elemen dan menggantinya dengan klonnya:
var clone = element.cloneNode(true);
Catatan: Ini akan mempertahankan atribut dan turunannya, tetapi tidak akan mempertahankan perubahan apa pun pada properti DOM.
Hapus penangan peristiwa "anonim" dari jenis tertentu
Cara lain adalah dengan menggunakan
removeEventListener()
tetapi saya rasa Anda sudah mencoba ini dan tidak berhasil. Ini tangkapannya :Anda pada dasarnya meneruskan fungsi anonim ke
addEventListener
sebagaieventReturner
mengembalikan fungsi.Anda memiliki dua kemungkinan untuk menyelesaikan ini:
Jangan gunakan fungsi yang mengembalikan fungsi. Gunakan fungsinya secara langsung:
function handler() { dosomething(); } div.addEventListener('click',handler,false);
Buat pembungkus untuk
addEventListener
itu menyimpan referensi ke fungsi yang dikembalikan dan membuat beberaparemoveAllEvents
fungsi aneh :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, ) }
Dan kemudian Anda bisa menggunakannya dengan:
addListener(div, 'click', eventReturner(), false) // and later removeAllListeners(div, 'click')
DEMO
Catatan: Jika kode Anda berjalan untuk waktu yang lama dan Anda membuat serta menghapus banyak elemen, Anda harus memastikan untuk menghapus elemen yang ada di dalamnya
_eventHandlers
saat Anda menghancurkannya.sumber
element.parentNode
bisa jadi nol. Mungkin harus memberi tanda jika di sekitar potongan kode di atas.Ini akan menghapus semua pendengar dari anak-anak tetapi akan lambat untuk halaman besar. Sangat sederhana untuk ditulis.
sumber
document.querySelector('body').outerHTML = document.querySelector('body').outerHTML
bekerja untuk saya.document.querySelector('body').outerHTML
Anda cukup mengetikdocument.body.outerHTML
Gunakan fungsi event listener sendiri
remove()
. Sebagai contoh:getEventListeners().click.forEach((e)=>{e.remove()})
sumber
getEventListeners
hanya tersedia di alat pengembang WebKit dan di FireBug. Bukan sesuatu yang bisa Anda sebut dalam kode Anda.getEventListeners()
. contoh:getEventListeners(document)
ataugetEventListeners(document.querySelector('.someclass'))
getEventListeners(document).click.forEach((e)=>{e.remove()})
menghasilkan kesalahan ini:VM214:1 Uncaught TypeError: e.remove is not a function
Seperti yang dikatakan corwin.amber, ada perbedaan antara Webkit dan yang lain.
Di Chrome:
getEventListeners(document);
Yang memberi Anda Objek dengan semua event listener yang ada:
Object click: Array[1] closePopups: Array[1] keyup: Array[1] mouseout: Array[1] mouseover: Array[1] ...
Dari sini Anda dapat menjangkau pendengar yang ingin Anda hapus:
getEventListeners(document).copy[0].remove();
Jadi Semua pendengar acara:
for(var eventType in getEventListeners(document)) { getEventListeners(document)[eventType].forEach( function(o) { o.remove(); } ) }
Di Firefox
Sedikit berbeda karena menggunakan pembungkus pendengar yang tidak berisi fungsi hapus. Anda harus mendapatkan pendengar yang ingin Anda hapus:
document.removeEventListener("copy", getEventListeners(document).copy[0].listener)
Semua pendengar acara:
for(var eventType in getEventListeners(document)) { getEventListeners(document)[eventType].forEach( function(o) { document.removeEventListener(eventType, o.listener) } ) }
Saya tersandung dengan posting ini mencoba untuk menonaktifkan perlindungan salinan situs berita yang mengganggu.
Nikmati!
sumber
getEventListeners
itu tidak ditentukan?Anda bisa menambahkan fungsi hook untuk mencegat semua panggilan ke
addEventHandler
. Pengait akan mendorong pawang ke daftar yang dapat digunakan untuk pembersihan. Sebagai contoh,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; }
Anda harus memasukkan kode ini di dekat bagian atas halaman web utama Anda (misalnya
index.html
). Selama pembersihan, Anda dapat melakukan loop melalui all_handlers, dan memanggil removeEventHandler untuk masing-masing. Jangan khawatir tentang memanggil removeEventHandler beberapa kali dengan fungsi yang sama. Itu tidak berbahaya.Sebagai contoh,
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); } }
Catatan: untuk IE gunakan Element, bukan EventTarget, dan ubah => menjadi berfungsi, dan berbagai hal lainnya.
sumber
Untuk melengkapi jawabannya, berikut adalah contoh dunia nyata dari menghapus peristiwa saat Anda mengunjungi situs web dan tidak memiliki kontrol atas kode HTML dan JavaScript yang dihasilkan.
Beberapa situs web yang mengganggu mencegah Anda untuk menyalin dan menempel nama pengguna pada formulir login, yang dapat dengan mudah dilewati jika
onpaste
acara tersebut ditambahkan denganonpaste="return false"
atribut HTML. Dalam hal ini kita hanya perlu mengklik kanan pada kolom input, pilih "Inspect element" di browser seperti Firefox dan hapus atribut HTML.Namun, jika acara tersebut ditambahkan melalui JavaScript seperti ini:
document.getElementById("lyca_login_mobile_no").onpaste = function(){return false};
Kami juga harus menghapus acara melalui JavaScript:
document.getElementById("lyca_login_mobile_no").onpaste = null;
Dalam contoh saya, saya menggunakan ID "lyca_login_mobile_no" karena itu adalah ID input teks yang digunakan oleh situs web yang saya kunjungi.
Cara lain untuk menghapus acara (yang juga akan menghapus semua acara) adalah dengan menghapus node dan membuat yang baru, seperti yang harus kita lakukan jika
addEventListener
digunakan untuk menambahkan acara menggunakan fungsi anonim yang tidak dapat kami hapusremoveEventListener
. Ini juga dapat dilakukan melalui konsol browser dengan memeriksa elemen, menyalin kode HTML, menghapus kode HTML, dan kemudian menempelkan kode HTML di tempat yang sama.Itu juga dapat dilakukan lebih cepat dan otomatis melalui JavaScript:
var oldNode = document.getElementById("lyca_login_mobile_no"); var newNode = oldNode.cloneNode(true); oldNode.parentNode.insertBefore(newNode, oldNode); oldNode.parentNode.removeChild(oldNode);
Pembaruan: jika aplikasi web dibuat menggunakan kerangka kerja JavaScript seperti Angular, tampaknya solusi sebelumnya tidak berfungsi atau merusak aplikasi. Solusi lain untuk memungkinkan menempelkan adalah menyetel nilai melalui JavaScript:
document.getElementById("lyca_login_mobile_no").value = "username";
Saat ini, saya tidak tahu apakah ada cara untuk menghapus semua validasi formulir dan peristiwa pembatasan tanpa merusak aplikasi yang seluruhnya ditulis dalam JavaScript seperti Angular.
sumber
angular memiliki polyfill untuk masalah ini, Anda dapat memeriksanya. Saya tidak banyak mengerti tapi mungkin itu bisa membantu.
const REMOVE_ALL_LISTENERS_EVENT_LISTENER = 'removeAllListeners';
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; } };
....
sumber
EVENT_NAME_SYMBOL_REGX
asalnya?Anda dapat menambahkan fungsi helper yang menghapus event listener, misalnya
function clearEventListener(element) { const clonedElement = element.cloneNode(true); element.replaceWith(clonedElement); return clonedElement; }
cukup kirimkan elemen ke fungsi dan hanya itu ...
sumber
var div = getElementsByTagName('div')[0]; /* first div found; you can use getElementById for more specific element */ div.onclick = null; // OR: div.onclick = function(){};
// edit
Saya tidak tahu metode apa yang Anda gunakan untuk melampirkan acara. Untuk
addEventListener
Anda dapat menggunakan ini:div.removeEventListener('click',functionName,false); // functionName is the name of your callback function
lebih detail
sumber
div.onClick = something
maka itu menetapkan onClick acara lain, tetapi yang sebelumnya tetap, jadi saya memiliki sebelumnya dan satu misalnya null ...addEventListener()
.addEventListener()
...Mungkin browser akan melakukannya untuk Anda jika Anda melakukan sesuatu seperti:
Salin
div
dan atributnya dan masukkan sebelum yang lama, lalu pindahkan konten dari yang lama ke yang baru dan hapus yang lama?sumber
Menghapus semua acara di
document
:Satu liner:
for (key in getEventListeners(document)) { getEventListeners(document)[key].forEach(function(c) { c.remove() }) }
Versi cantik:
for (key in getEventListeners(document)) { getEventListeners(document)[key].forEach(function(c) { c.remove() }) }
sumber
Chrome saja
Saat saya mencoba untuk menghapus EventListener dalam pengujian Protractor dan tidak memiliki akses ke Listener dalam pengujian, berikut ini berfungsi untuk menghapus semua event listener dari satu jenis:
function(eventType){ getEventListeners(window).[eventType].forEach( function(e){ window.removeEventListener(eventType, e.listener) } ); }
Saya harap ini membantu seseorang karena jawaban sebelumnya menggunakan metode "hapus" yang sejak itu tidak berfungsi lagi.
sumber
Salah satu metodenya adalah menambahkan event listener baru yang memanggil e.stopImmediatePropagation ().
sumber