2016-03-28 3 views
0

Ok, also habe ich diesen kleinen Hack getan, um zu erreichen, was ich brauche, um mehrere Ereignisse zu verschiedenen Zeiten zu einer bestimmten Funktion hinzuzufügen.So binden Sie Ereignisse an eine Funktion ohne ein DOM-Objekt

$("#handler").bind("click",function(){ alert(1); }); 
$("#handler").bind("click",function(){ alert(2); }); 
$("#handler").bind("click",function(){ alert(3); }); 

Wenn ich einfach $("#handler").click() aufrufen, werden alle diese Ereignisse ausgelöst.

Frage ist, kann ich dies tun, ohne irgendein willkürliches HTML-Objekt zu machen, um es zu binden?

Was ist mit einer Standard-JavaScript-Funktion zu tun?

function handler(){ alert(1); } 
function handler(){ alert(2); } 
function handler(){ alert(3); } 
handler(); 

^Dieses feuert nur die letzte, und nicht alle 3. Wie kann ich mehrere Ereignisse in einer Funktion statt auf ein DOM-Element binden?

+0

Binden Sie das Ereignis nur einmal. – Tushar

+0

@Tushar Ja natürlich, dann müsste ich die Frage nicht richtig stellen? Problem, die Bindungen treten zu verschiedenen Teilen der Laufzeit auf. Aber danke für die Eingabe – RealWorldCoder

+0

hast du überlegt, mit loop? es feuert den letzten, weil die letzte Lesefunktion mit der ersten und zweiten identisch war. –

Antwort

1

Wenn Sie wirklich nur nach einer Möglichkeit suchen, einzelne Funktionen zu einem größeren "Funktionssatz" zusammenzufassen, den Sie später auf einmal auslösen können, könnte dies über ein Set Objekt in Javascript erreicht werden.Beispiel:

// define the Set object that you want to store the functions inside: 
var handlerFunctionCollection = new Set(); 


// add individual functions to the Set: 
handlerFunctionCollection.add(function(){ console.log(1); }); 
handlerFunctionCollection.add(function(){ console.log(2); }); 
handlerFunctionCollection.add(function(){ console.log(3); }); 

// trigger all functions in set using forEach on Set 
// and call() method on stored Function object: 
handlerFunctionCollection.forEach(function(handlerFunction) { 
    if(handlerFunction instanceof Function) { 
     handlerFunction.call(); 
    } 
}); 

Bitte beachte, dass ich diese Interpretation Ihrer Frage auf Sie basiert bin stützen sagen:

Wenn einfach $("#handler").click() Ich nenne es feuert alle diese Ereignisse.

, die Sie nicht tatsächlich auf der Suche nach einer Möglichkeit, Funktionen zu binden direkt an ein Ereignis vermuten läßt, sondern eine Möglichkeit, mehrere Funktionen in einem Ort, auslösen, da sonst würden Sie nicht das click Ereignis manuell Auslösung werden.

Ein Vorteil eines Set über einen Array Objekt oder eine ähnliche Sammlung besteht darin, dass die Mitglieder einer Set sind einzigartig, so dass, wenn Sie die gleiche Funktion mehrmals hinzuzufügen waren versuchen (aus Versehen oder aus anderen Gründen), die hinzugefügt Function Objekt würde nur einmal in der Set, so dass es daher nur einmal ausgelöst würde, wenn die forEach ausgelöst würde, da es nur einmal in der Set statt für jedes Mal, dass es hinzugefügt wurde.

1

In JavaScript ist jede Funktion tatsächlich ein Funktionsobjekt.

In Javascript, wenn Sie mehrere Funktionen mit demselben Namen definieren, wird der letzte ausgeführt. JavaScript functions sind nicht polymorphic wie Funktionen in vielen anderen Sprachen, in denen Sie in anderen Sprachen funcA(parm1) und funcA(parm1, parm2) als zwei separate Funktionen mit der eine haben, die abhängig von der Anzahl der übergebenen Parameter ausgeführt wird.

In Ihrem Fall müssen Sie eine Funktion auf eine Weise deklarieren, die verschiedene Situationen innerhalb des Funktionsumfangs behandeln kann.

0

Sie suchen nach dem Konzept Observer oder Publisher/Subscriber ("PubSub").

Diese sind ziemlich einfach auf eigene Faust zu erstellen.
Hier ist eine leicht bereinigte Version des Application-only-Codes (der möglicherweise auf DOM-ready ausgeführt wird, oder was auch immer), um den Demo-Code unten auszuführen.

const trigger = $("#Trigger"); 
const system = Publisher(); 

// add my listeners 
system 
.on("trigger", triggerContentUpdate) 
.on("update", updateView) 
.on("update", logUpdate); // note how I have two things bound to the same event 

// something that kicks off the "trigger" event 
// could be a timer, or an AJAX call, or anything else 
trigger.onclick =() => system.fire("trigger"); 

Angenommen, Sie hatten eine Publisher Bibliothek und hatte die oben Listener-Funktionen in Ihrer Anwendung, das ist so ziemlich alles, von dem JS Sie schreiben würde, um die Demo unter Arbeit zu machen.

Die Bibliothek schrieb ich als Praxis, und die Implementierung der Demo sind unten.

/*** LIBRARY CODE ***/ 
 

 
// Channel.js 
 
const Channel =() => { 
 
    const listeners = new Set(); 
 

 
    const channel = { 
 

 
    listen(listener) { 
 
     listeners.add(listener); 
 
     return channel; 
 
    }, 
 

 
    ignore(listener) { 
 
     listeners.delete(listener); 
 
     return channel; 
 
    }, 
 

 
    notify(data) { 
 
     listeners.forEach(react => react(data)); 
 
     return channel; 
 
    } 
 
    }; 
 

 
    return channel; 
 
}; 
 

 
// Publisher.js 
 
const Publisher =() => { 
 
    const channels = {}; 
 

 
    function getChannel(name) { 
 
    const channel = channels[name] || Channel(); 
 
    channels[name] = channel; 
 
    return channel; 
 
    } 
 

 
    const publisher = { 
 

 
    on(name, subscriber) { 
 
     getChannel(name).listen(subscriber); 
 
     return publisher; 
 
    }, 
 

 
    off(name, subscriber) { 
 
     getChannel(name).ignore(subscriber); 
 
     return publisher; 
 
    }, 
 

 
    fire(name, data) { 
 
     getChannel(name).notify(data); 
 
     return publisher; 
 
    } 
 

 
    }; 
 

 
    return publisher; 
 
} 
 

 
/*** END OF LIBRARY CODE ***/ 
 

 

 

 
/*** APPLICATION CODE ***/ 
 

 
// const Publisher = require("publisher"); or import Publisher from "publisher"; 
 

 
const $ = selector => document.querySelector(selector); 
 

 
const trigger = $("#Trigger"); 
 
const input = $("#Content"); 
 
const output = $("#Result"); 
 
const log = $("#Log"); 
 

 
const system = Publisher(); 
 

 
system 
 
    .on("trigger",() => { 
 
    const content = input.value; 
 
    system.fire("update", content); 
 
    }) 
 
    .on("update", content => output.value = content) 
 
    // normally, I never use innerHTML, and my logic and view are never attached, but this is dirt-simple now 
 
    .on("update", content => log.innerHTML += `<li>[${ (new Date()).toISOString() }]: ${content}</li>`); 
 

 
trigger.onclick =() => system.fire("trigger"); 
 

 
/*** END OF APPLICATION CODE ***/
<h3>Input</h3> 
 
<div> 
 
    <input id="Content" type="text"> 
 
    <button id="Trigger">Update</button> 
 
</div> 
 
<h3>Output</h3> 
 
<output id="Result"></output> 
 

 
<h3>Log</h3> 
 
<ul id="Log"></ul>

Natürlich, ich bin mit relativ modernen Syntax, aber nichts, was nicht in älteren kompatiblen Code neu geschrieben werden kann oder transpiled und polyfill gegeben, den ganzen Weg gehen zu IE7/8 Unterstützung.

Wenn ich ein beliebiges Objekt zu einem Verleger machen wollte, könnte ich das auch schnell machen.

+0

Ist das Javascript? – RealWorldCoder

+1

@RealWorldCoder es ist 100% JavaScript. Natives, normales, tägliches JavaScript. Sie können alle Pfeilfunktionen durch altmodische 'Funktion' ersetzen, Sie können die' Set' durch '[]' ersetzen und zusätzliche Checks hinzufügen, um keine doppelten Listener einzufügen (etwas, das ein Set für Sie tut). Sie können alle "const" durch "var" ersetzen. Und du bist wieder bei altmodischen JS. Wenn Sie jedoch feststellen, dass Chrome oder FireFox oder ein anderer Browser, der sich selbst respektiert, ausgeführt wird, sollte das Beispiel gut funktionieren. – Norguard

+0

@RealWorldCoder einen Blick auf http://BabelJS.io, die ES6 (die oben genannten) in ES3 (IE8 +) kompatiblen Code verwandelt, wenn in Verbindung mit einem Polyfill für Objekte wie 'Set' und' Map' – Norguard

Verwandte Themen