जावास्क्रिप्ट / DOM: DOM ऑब्जेक्ट की सभी घटनाओं को कैसे हटाएं?


97

बस सवाल: क्या किसी वस्तु के सभी घटनाओं को हटाने का कोई तरीका है, जैसे कि 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);
}

आप घटनाओं को कैसे संलग्न करते हैं?
फेलिक्स क्लिंग

2
शीर्षक वस्तु के तत्वों के बारे में पूछता है , जबकि वास्तविक सवाल घटनाओं के बारे में पूछता है । क्या आप बाल तत्वों या घटनाओं को हटाना चाहते हैं?
पियर वेसलैंडर

ओह d * mn, यही कारण है कि मैं कुछ और सोच रहा था जब मैंने लिखा था कि ... मैं घटनाओं के
फ्लोरियन मुलर

मुझे सटीक मामला नहीं पता है लेकिन कुछ मामलों में वर्कअराउंड के रूप में आप 'ऑन *' विधियों (जैसे div.onclick = function) का उपयोग कर सकते हैं, जो हमेशा एकल श्रोता के साथ काम करता है और इसे हटाना आसान होता है div.onclick=null। बेशक आपको addEventListenerइस मामले में पूरी तरह से उपयोग नहीं करना चाहिए क्योंकि यह एक अलग श्रोता को एक से अलग करेगा onclick
वेन्यूमस

जवाबों:


106

मुझे यकीन नहीं है कि सभी घटनाओं को हटाने के साथ आपका क्या मतलब है । एक विशेष प्रकार की घटना के लिए सभी हैंडलर निकालें या एक प्रकार के सभी इवेंट हैंडलर?

सभी ईवेंट हैंडलर निकालें

यदि आप सभी ईवेंट हैंडलर (किसी भी प्रकार के) को निकालना चाहते हैं, तो आप तत्व को क्लोन कर सकते हैं और इसे अपने क्लोन से बदल सकते हैं:

var clone = element.cloneNode(true);

नोट: यह विशेषताओं और बच्चों को संरक्षित करेगा, लेकिन यह DOM संपत्तियों में कोई बदलाव नहीं करेगा।


विशिष्ट प्रकार के "अनाम" ईवेंट हैंडलर निकालें

दूसरे तरीके का उपयोग करना है, removeEventListener()लेकिन मुझे लगता है कि आपने पहले ही यह कोशिश की थी और यह काम नहीं किया। यहाँ पकड़ है :

addEventListenerएक अनाम फ़ंक्शन पर कॉल करना हर बार एक नया श्रोता बनाता है। removeEventListenerकिसी अनाम फ़ंक्शन पर कॉल करने का कोई प्रभाव नहीं पड़ता है । एक अनाम फ़ंक्शन प्रत्येक बार जब यह कहा जाता है, तो एक अद्वितीय ऑब्जेक्ट बनाता है, यह किसी मौजूदा ऑब्जेक्ट का संदर्भ नहीं है, हालांकि यह एक कॉल कर सकता है। इस तरह से एक ईवेंट श्रोता को जोड़ने पर सुनिश्चित करें कि इसे केवल एक बार जोड़ा गया है, यह स्थायी है (हटाया नहीं जा सकता) जब तक कि इसे जोड़ा गया ऑब्जेक्ट नष्ट नहीं हो जाता।

आप अनिवार्य रूप से एक फ़ंक्शन को रिटर्न के addEventListenerरूप में एक अनाम फ़ंक्शन पास कर रहे हैं eventReturner

इसे हल करने के लिए आपके पास दो संभावनाएँ हैं:

  1. एक फ़ंक्शन का उपयोग न करें जो एक फ़ंक्शन देता है। सीधे फ़ंक्शन का उपयोग करें:

    function handler() {
        dosomething();
    }
    
    div.addEventListener('click',handler,false);
    
  2. 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जब आप उन्हें नष्ट करें , तो उसमें मौजूद तत्वों को हटा दें ।


@ फ़्लोरियन: निश्चित रूप से, कोड में सुधार किया जा सकता है, लेकिन यह आपको एक विचार देना चाहिए ... खुश कोडिंग!
फेलिक्स क्लिंग

2
क्या आपने एक से अधिक div तत्व के साथ यह कोशिश की है? नोड संस्करण वास्तव में एक स्ट्रिंग में बदल जाएगा, उदाहरण के लिए '[ऑब्जेक्ट HTMLDivElement]' जिसका अर्थ है कि आप एक ही नोड में सब कुछ जोड़ रहे हैं।
cstruter

@ कंप्यूटर: ठीक है ... यह मेरे जावास्क्रिप्ट के शुरुआती दिनों में था ... जब मुझे कुछ और समय मिलेगा तो मैं कोड को सही कर दूंगा। मुझे बताने के लिए धन्यवाद।
फेलिक्स क्लिंग

मुझे लगता है कि एक टाइपो है, addListener addEvent होना चाहिए
AGamePlayer

ध्यान दें कि element.parentNodeशून्य हो सकता है। शायद ऊपर के कोड के उस टुकड़े के चारों ओर एक अगर जाँच करनी चाहिए।
thecoolmacdude

43

यह सभी श्रोताओं को बच्चों से दूर कर देगा लेकिन बड़े पृष्ठों के लिए धीमा होगा। लिखने में क्रूरतापूर्ण।

element.outerHTML = element.outerHTML;

2
बहुत बढ़िया जवाब। लीफ नोड्स के लिए, यह सबसे अच्छा विचार है।
user3055938

3
document.querySelector('body').outerHTML = document.querySelector('body').outerHTMLमेरे लिए काम किया।
रेयान

2
@ document.querySelector('body').outerHTMLआप के बजाय रयान सिर्फ टाइप कर सकते हैंdocument.body.outerHTML
जे दादानिया

28

ईवेंट श्रोता के स्वयं के फ़ंक्शन का उपयोग करें remove()। उदाहरण के लिए:

getEventListeners().click.forEach((e)=>{e.remove()})

2
निश्चित नहीं कि यह सही उत्तर क्यों नहीं है। यह प्रश्न SO पर इतनी बार दिखाई देता है और क्लोन पद्धति का उपयोग करके समस्या को हल कर सकता है।
जिमासुन

42
ऐसा लगता है कि getEventListenersयह केवल WebKit dev टूल्स और FireBug में उपलब्ध है। ऐसा कुछ नहीं जिसे आप सिर्फ अपने कोड में कॉल कर सकते हैं।
corwin.amber 17

1
यह काम करने में परेशानी हो रही थी, आप एक तर्क के रूप में एक वस्तु को पास करते हैं getEventListeners()। उदाहरण: getEventListeners(document)याgetEventListeners(document.querySelector('.someclass'))
ल्यूक

10
यह केवल क्रोम कंसोल पर काम करने लगता है । यहां तक ​​कि पेज पर आपकी स्क्रिप्ट पर भी यह काम नहीं करता है।
रिबेल रिबेरो

4
getEventListeners(document).click.forEach((e)=>{e.remove()})इस त्रुटि को उत्पन्न करता है:VM214:1 Uncaught TypeError: e.remove is not a function
रेयान

11

जैसा कि corwin.amber कहता है, वेबकिट अन्य लोगों के बीच मतभेद हैं।

क्रोम में:

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(); }
   ) 
}

फ़ायरफ़ॉक्स में

थोड़ा अलग है क्योंकि यह एक श्रोता आवरण का उपयोग करता है जिसमें कोई निष्कासन फ़ंक्शन नहीं होता है। आपको वह श्रोता प्राप्त करना होगा जिसे आप हटाना चाहते हैं:

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) }
  ) 
}

मैं एक समाचार वेबसाइट की कष्टप्रद प्रतिलिपि सुरक्षा को अक्षम करने की कोशिश कर इस पोस्ट के साथ ठोकर खाई।

का आनंद लें!


श्रोताओं को हटाने के लिए लक्षित करने के लिए यह सबसे अच्छा उत्तर है, जैसे कि दस्तावेज़ के नोड पर किसी विशिष्ट श्रोता को उसके सभी श्रोताओं को हटाए बिना हटाने की स्थिति में।
ट्रेवर

यह काम ठीक है और सबसे अच्छा जवाब। @Jmakuc बहुत बहुत धन्यवाद।
थावमानी कासी

5
फ़ायरफ़ॉक्स मुझे बता रहा है कि getEventListenersपरिभाषित नहीं है?
रोवेको

यह एक खराब समाधान है क्योंकि वर्तमान में getEventListeners केवल क्रोम द्वारा समर्थित है।
माइकल पैसिओन

1

आप सभी कॉल को इंटरसेप्ट करने के लिए एक हुक फंक्शन जोड़ सकते हैं 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) के शीर्ष के पास यह कोड डालना चाहिए । सफाई के दौरान, आप सभी_हैंडलर के माध्यम से लूप कर सकते हैं, और प्रत्येक के लिए 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 के बजाय तत्व का उपयोग करें, और फ़ंक्शन = और विभिन्न अन्य चीजों के लिए = = बदलें।


0

उत्तरों को पूरा करने के लिए, जब आप वेबसाइटों पर जा रहे हैं तो घटनाओं को हटाने के वास्तविक-विश्व उदाहरण हैं और उत्पन्न HTML और जावास्क्रिप्ट कोड पर नियंत्रण नहीं है।

कुछ कष्टप्रद वेबसाइटें आपको लॉगिन फॉर्म पर उपयोगकर्ता नाम कॉपी-पेस्ट करने से रोक रही हैं, जो HTML विशेषता के onpasteसाथ ईवेंट जोड़े जाने पर आसानी से बायपास हो सकते हैं onpaste="return false"। इस मामले में हमें बस इनपुट क्षेत्र पर राइट क्लिक करने की आवश्यकता है, फ़ायरफ़ॉक्स जैसे ब्राउज़र में "इंस्पेक्ट एलिमेंट" चुनें और एचटीएमएल विशेषता को हटा दें।

हालाँकि, यदि ईवेंट को इस तरह जावास्क्रिप्ट के माध्यम से जोड़ा गया था:

document.getElementById("lyca_login_mobile_no").onpaste = function(){return false};

हमें जावास्क्रिप्ट के माध्यम से भी घटना को हटाना होगा:

document.getElementById("lyca_login_mobile_no").onpaste = null;

मेरे उदाहरण में, मैंने आईडी "lyca_login_mobile_no" का उपयोग किया क्योंकि यह उस वेबसाइट द्वारा उपयोग की जाने वाली पाठ इनपुट आईडी थी जिसका मैं दौरा कर रहा था।

ईवेंट को हटाने का एक और तरीका (जो सभी घटनाओं को भी हटा देगा) नोड को हटाने और एक नया बनाने के लिए है, जैसे कि हमें ऐसा करना होगा यदि addEventListenerएक गुमनाम फ़ंक्शन का उपयोग करके ईवेंट को जोड़ने के लिए उपयोग किया गया था जिसे हम नहीं निकाल सकते removeEventListener। यह एक तत्व का निरीक्षण करके, HTML कोड की प्रतिलिपि बनाकर, HTML कोड को हटाकर और फिर उसी स्थान पर HTML कोड चिपकाकर भी ब्राउज़र कंसोल के माध्यम से किया जा सकता है।

इसे जावास्क्रिप्ट के माध्यम से तेज और स्वचालित भी किया जा सकता है:

var oldNode = document.getElementById("lyca_login_mobile_no");
var newNode = oldNode.cloneNode(true);
oldNode.parentNode.insertBefore(newNode, oldNode);
oldNode.parentNode.removeChild(oldNode);

अद्यतन: अगर वेब ऐप को एंगुलर जैसे जावास्क्रिप्ट फ्रेमवर्क का उपयोग करके बनाया गया है, तो ऐसा लगता है कि पिछले समाधान ऐप को काम या तोड़ नहीं रहे हैं। चिपकाने की अनुमति देने के लिए एक और समाधान जावास्क्रिप्ट के माध्यम से मान सेट करना होगा:

document.getElementById("lyca_login_mobile_no").value = "username";

फिलहाल, मुझे नहीं पता कि एंगुलर जैसे जावास्क्रिप्ट में पूरी तरह से लिखे गए ऐप को तोड़ने के बिना सभी फॉर्म सत्यापन और प्रतिबंध की घटनाओं को हटाने का कोई तरीका है या नहीं।


0

कोणीय में इस मुद्दे के लिए एक पॉलीफ़िल है, आप जांच कर सकते हैं। मुझे ज्यादा समझ नहीं थी लेकिन शायद यह मदद कर सके।

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;
        }
    };

....


कहाँ EVENT_NAME_SYMBOL_REGXसे आने वाला है?
एलियास ज़मरिया

0

आप एक सहायक फ़ंक्शन जोड़ सकते हैं जो उदाहरण के लिए ईवेंट श्रोता को साफ़ करता है

function clearEventListener(element) {
 const clonedElement = element.cloneNode(true);
element.replaceWith(clonedElement);
return clonedElement;
}

बस फ़ंक्शन के लिए तत्व में पास है और यह है ...


-1
var div = getElementsByTagName('div')[0]; /* first div found; you can use getElementById for more specific element */
div.onclick = null; // OR:
div.onclick = function(){};

// संपादित करें

मुझे नहीं पता था कि आप घटनाओं को संलग्न करने के लिए किस पद्धति का उपयोग कर रहे हैं। के लिए addEventListenerआप इस का उपयोग कर सकते हैं:

div.removeEventListener('click',functionName,false); // functionName is the name of your callback function

अधिक जानकारी


1
अगर मैं इसे सेट करता हूँ, div.onClick = somethingतो यह एक और घटना को सेट करता है पर क्लिक करें, लेकिन पिछले रहता है, इसलिए मैं पिछले और उदाहरण के लिए एक पर है ...
फ्लोरियन मुलर

1
यदि हैंडलर के माध्यम से जोड़ा जाता है तो काम नहीं करेगा addEventListener()
फेलिक्स क्लिंग

@ फ़्लोरियन: नहीं, यह सच नहीं है। यदि आप किसी ईवेंट हैंडलर को जोड़ने के इस तरीके का उपयोग करते हैं, तो आपके पास किसी ईवेंट के लिए केवल एक हैंडलर हो सकता है । लेकिन अगर आप उपयोग करते हैं तो इससे फर्क पड़ता है addEventListener()...
फेलिक्स क्लिंग

लेकिन मैंने इसे इस तरह से देखा है, इसलिए अगर मैंने पिछले फ़ंक्शन को फिर से जोड़ा, तो इसे दो बार कहा जाएगा ... और, जैसे फेलिक्स किंग कहते हैं, यह एडवेंटिस्टलिस्ट के साथ काम नहीं करता है ...
फ्लोरियन मुलर

-1

यदि आप कुछ ऐसा करते हैं तो ब्राउज़र आपके लिए यह कर देगा:

divउसकी विशेषताओं को कॉपी करें और पुराने से पहले डालें, फिर सामग्री को पुराने से नए में ले जाएं और पुराने को हटा दें?


अब यह वास्तव में एक अच्छा विचार है, लेकिन पूरी तरह से निष्प्रभावी है, अगर आपको 1'000 और 1'000'000 के बीच के डिबेट्स के लिए यह करना है ... हां, यह एक बड़ी परियोजना है;)
फ्लोरियन मुलर

6
एक पृष्ठ में 1M divs? आप इससे पहले अन्य परेशानियों में पड़ेंगे;) हो सकता है कि इवेंट डेलिगेशन का उपयोग करें ...
माइक

-1

सभी घटनाओं को हटानाdocument :

एक लाइन:

for (key in getEventListeners(document)) { getEventListeners(document)[key].forEach(function(c) { c.remove() }) }

सुंदर संस्करण:

for (key in getEventListeners(document)) {
  getEventListeners(document)[key].forEach(function(c) {
    c.remove()
  })   
}

-1

केवल क्रोम

जैसा कि मैं एक प्रोटेक्टर परीक्षण के भीतर एक EventListener को हटाने की कोशिश कर रहा हूं और परीक्षण में श्रोता तक पहुंच नहीं है, निम्नलिखित सभी कार्यों को एक ही प्रकार के श्रोताओं को निकालने के लिए करता है:

function(eventType){
    getEventListeners(window).[eventType].forEach(
        function(e){
            window.removeEventListener(eventType, e.listener)
        }
    );
}

मुझे उम्मीद है कि यह किसी को मदद करता है क्योंकि पिछले उत्तर "हटाने" विधि का उपयोग कर रहे थे जो तब से अब काम नहीं करता है।


हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.