Ist es möglich, dass in JS ein Ereignis ausgelöst wird, wenn sich der Wert einer bestimmten Variablen ändert? JQuery wird akzeptiert.
javascript
jquery
dom-events
rashcroft22
quelle
quelle
variable
, aber alle Antworten hier beziehen sich aufproperty
. Ich frage mich, ob wir auflocal variable
Veränderungen hören können .Antworten:
Ja, das ist jetzt völlig möglich!
Ich weiß, dass dies ein alter Thread ist, aber jetzt ist dieser Effekt mit Accessoren (Getter und Setter) möglich: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Working_with_Objects#Defining_getters_and_setters
Sie können ein Objekt wie dieses definieren, in dem
aInternal
das Feld dargestellt wirda
:Anschließend können Sie einen Listener wie folgt registrieren:
Wenn also etwas den Wert von ändert
x.a
, wird die Listener-Funktion ausgelöst. Wenn Sie die folgende Zeile ausführen, wird das Alarm-Popup angezeigt:Ein Beispiel finden Sie hier: https://jsfiddle.net/5o1wf1bn/1/
Sie können auch ein Array von Listenern anstelle eines einzelnen Listener-Slots verwenden, aber ich wollte Ihnen das einfachste Beispiel geben.
quelle
this.aListener(val)
, sondern alle Listener-Funktionen durchlaufen und jeden einzelnen Listener aufrufenval
. In der Regel wird die MethodeaddListener
anstelle von aufgerufenregisterListener
.Die meisten Antworten auf diese Frage sind entweder veraltet, ineffektiv oder erfordern die Aufnahme großer aufgeblähter Bibliotheken:
Heute können Sie das Proxy- Objekt verwenden , um an einem Objekt vorgenommene Änderungen zu überwachen (und abzufangen). Es wurde speziell für das entwickelt, was das OP zu tun versucht. Hier ist ein einfaches Beispiel:
Die einzigen Nachteile des
Proxy
Objekts sind:Proxy
Objekt ist in älteren Browsern (z. B. IE11) nicht verfügbar, und die Polyfüllung kann dieProxy
Funktionalität nicht vollständig replizieren .Date
) nicht immer wie erwartet - dasProxy
Objekt wird am besten mit einfachen Objekten oder Arrays gepaart.Wenn Sie Änderungen an einem verschachtelten Objekt beobachten müssen , müssen Sie eine spezielle Bibliothek wie Observable Slim (die ich veröffentlicht habe) verwenden, die folgendermaßen funktioniert:
quelle
target.hello_world = "test"
) ändertyou don't actually watch changes on the target object but only on proxy object
- Das ist nicht ganz richtig. DasProxy
Objekt wird nicht geändert - es verfügt nicht über eine eigene Kopie des Ziels.you just want to know when a property change on the target object
- Sie können dies mit a erreichenProxy
, das ist einer der primären Anwendungsfälle für Proxys.target
müssen Sie dies über einen Proxy tun. Diesproxy.hello_world = "test"
bedeutet jedoch nicht, dass Sie den Proxy ändern. Der Proxy bleibt unverändert undtarget
wird geändert (sofern Ihr Set-Handler dafür konfiguriert ist). Es hört sich so an, als ob Sie nicht direkt beobachten könnentarget.hello_world = "test"
. Das ist wahr. Einfache Variablenzuweisungen geben kein Ereignis aus. Deshalb müssen wir Werkzeuge verwenden, wie sie in den Antworten auf diese Frage beschrieben sind.It sounds like your point is that you cannot directly observe target.hello_world = "test". That is true.
das ist genau mein Punkt. In meinem Fall habe ich ein Objekt an einer anderen Stelle erstellt und durch einen anderen Code aktualisiert. In diesem Fall ist ein Proxy nicht hilfreich, da die Änderungen am Ziel vorgenommen werden.Nein.
Aber wenn es wirklich so wichtig ist, haben Sie zwei Möglichkeiten (die erste wird getestet, die zweite nicht):
Verwenden Sie zunächst Setter und Getter wie folgt:
dann kannst du so etwas machen wie:
Stellen Sie dann den Listener wie folgt ein:
Zweitens habe ich tatsächlich vergessen, ich werde einreichen, während ich darüber nachdenke :)
EDIT: Oh, ich erinnere mich :) Sie könnten eine Uhr auf den Wert setzen:
Angesichts von myobj oben mit 'a' darauf:
quelle
Verwenden von
Prototype
: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/definePropertyAnderes Beispiel
quelle
varw
erfordert 2 Argumente, aber ein Teil Ihres Beispiels zeigt die aufgerufene Funktion nur mit dem Wertparameter.Es tut mir leid, einen alten Thread aufzurufen, aber hier ist ein kleines Handbuch für diejenigen, die (wie ich!) Nicht sehen, wie das Beispiel von Eli Grey funktioniert:
Hoffe das kann jemandem helfen
quelle
Als Antwort von Luke Schafer ( Hinweis : Dies bezieht sich auf seinen ursprünglichen Beitrag; der ganze Punkt hier bleibt jedoch nach der Bearbeitung gültig ) würde ich auch ein Paar Get / Set-Methoden vorschlagen, um auf Ihren Wert zuzugreifen.
Ich würde jedoch einige Änderungen vorschlagen (und deshalb poste ich ...).
Ein Problem mit diesem Code besteht darin, dass auf das Feld
a
des Objektsmyobj
direkt zugegriffen werden kann, sodass es möglich ist, darauf zuzugreifen / seinen Wert zu ändern, ohne die Listener auszulösen:Verkapselung
Um sicherzustellen, dass die Zuhörer tatsächlich angerufen werden, müssten wir diesen direkten Zugriff auf das Feld verbieten
a
. Wie geht das? Verwenden Sie einen Verschluss !Jetzt können Sie die Listener auf dieselbe Weise erstellen und hinzufügen, wie von Luke vorgeschlagen, aber Sie können sicher sein, dass es keine Möglichkeit gibt
a
, unbemerkt zu lesen oder zu schreiben !Programmiertes Hinzufügen gekapselter Felder
Immer noch auf Lukes Spur, schlage ich jetzt eine einfache Möglichkeit vor, gekapselte Felder und die entsprechenden Getter / Setter mithilfe eines einfachen Funktionsaufrufs zu Objekten hinzuzufügen.
Beachten Sie, dass dies nur dann richtig funktionieren mit Werttypen . Damit dies funktioniert mit Referenztypen , eine Art tiefer Kopie müßte (siehe implementiert diese ein , zum Beispiel).
Dies funktioniert genauso wie zuvor: Wir erstellen eine lokale Variable für eine Funktion und anschließend einen Abschluss.
Wie benutzt man es? Einfach:
quelle
Wenn Sie jQuery {UI} verwenden (das jeder verwenden sollte :-)), können Sie .change () mit einem versteckten <input /> -Element verwenden.
quelle
<input/>
Element anhängen ?<input type="hidden" value="" id="thisOne" />
und mit jQuery$("#thisOne").change(function() { do stuff here });
und$("#thisOne").val(myVariableWhichIsNew);
dann dem.change()
Willen Feuer.var1 = 'new value';
zu ändern, legen Sie stattdessen den Wert dieser versteckten Eingabe fest und fügen dann einen Listener hinzu, um die Variable zu ändern.$("#val1").on('change', function(){ val1 = this.val(); ... do the stuff that you wanted to do when val1 changed... }); $("#val1").val('new value');
AngularJS
(Ich weiß, dass dies nicht der Fall istJQuery
, aber das könnte helfen. [Pure JS ist nur theoretisch gut]):Dabei ist "Daten" der Name Ihrer Variablen im Bereich.
Es gibt einen Link zu doc.
quelle
$scope.$apply()
es ausgeführt wirdFür diejenigen, die ein paar Jahre später abstimmen:
Für die meisten Browser (und IE6 +) ist eine Lösung verfügbar, die das Ereignis onpropertychange und die neuere Spezifikation defineProperty verwendet. Der kleine Haken ist, dass Sie Ihre Variable zu einem Dom-Objekt machen müssen.
Alle Einzelheiten:
http://johndyer.name/native-browser-get-set-properties-in-javascript/
quelle
Die Funktionalität, nach der Sie suchen, kann mithilfe der Methode "defineProperty ()" erreicht werden, die nur modernen Browsern zur Verfügung steht:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty
Ich habe eine jQuery-Erweiterung geschrieben, die ähnliche Funktionen bietet, wenn Sie mehr browserübergreifende Unterstützung benötigen:
https://github.com/jarederaj/jQueue
quelle
Nicht direkt: Sie benötigen ein Paar Getter / Setter mit einer "addListener / removeListener" -Schnittstelle ... oder einem NPAPI-Plugin (aber das ist insgesamt eine andere Geschichte).
quelle
oder
oder
quelle
Eine ziemlich einfache und vereinfachende Lösung besteht darin, nur einen Funktionsaufruf zu verwenden, um den Wert der globalen Variablen festzulegen, und niemals ihren Wert direkt festzulegen. Auf diese Weise haben Sie die vollständige Kontrolle:
Es gibt keine Möglichkeit, dies durchzusetzen, es erfordert lediglich Programmierdisziplin ... obwohl Sie
grep
(oder etwas Ähnliches) verwenden können, um zu überprüfen, ob Ihr Code den Wert von nirgendwo direkt festlegtglobalVar
.Oder Sie können es in ein Objekt und Benutzer-Getter- und Setter-Methoden einkapseln ... nur ein Gedanke.
quelle
var
zugegriffen werden kann - wie dies bei Variablen der Fall ist, mit denen in ES6-Modulen deklariert wurde - ist dies die einzige Lösung.Bitte Jungs, erinnert euch, die erste Frage war für VARIABLEN, nicht für OBJEKTE;)
Zusätzlich zu allen obigen Antworten habe ich eine winzige Bibliothek namens forTheWatch.js erstellt , die auf dieselbe Weise Änderungen an normalen globalen Variablen in Javascript abfängt und zurückruft .
Kompatibel mit JQUERY-Variablen, keine Verwendung von OBJECTS erforderlich, und Sie können bei Bedarf direkt ein ARRAY mehrerer Variablen übergeben.
Wenn es hilfreich sein kann ...: https://bitbucket.org/esabora/forthewatch
Grundsätzlich müssen Sie nur die Funktion aufrufen:
watchIt("theVariableToWatch", "varChangedFunctionCallback");
Und Entschuldigung im Voraus, wenn nicht relevant.
quelle
Der einfachste Weg, den ich gefunden habe, ausgehend von dieser Antwort :
Und dann:
quelle
In meinem Fall habe ich versucht herauszufinden, ob eine Bibliothek, die ich in mein Projekt aufgenommen habe, meine neu definiert hat
window.player
. Zu Beginn meines Codes habe ich einfach Folgendes getan:quelle
Es ist nicht direkt möglich.
Dies kann jedoch mit CustomEvent erfolgen: https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent
Die folgende Methode akzeptiert ein Array von Variablennamen als Eingabe und fügt einen Ereignis-Listener für jede Variable hinzu und löst das Ereignis für Änderungen am Wert der Variablen aus.
Die Methode verwendet Polling, um die Änderung des Werts zu erkennen. Sie können den Wert für das Zeitlimit in Millisekunden erhöhen.
Durch Aufrufen der Methode:
Es erkennt die Änderungen an den Variablen Benutzername und Benutzer-ID.
quelle
Mit Hilfe von Getter und Setter können Sie eine JavaScript-Klasse definieren, die so etwas tut.
Zuerst definieren wir unsere Klasse mit dem Namen
MonitoredVariable
:Angenommen, wir möchten auf
money
Änderungen warten, erstellen wir eine InstanzMonitoredVariable
mit anfänglichem Geld0
:Dann könnten wir seinen Wert erhalten oder einstellen, indem wir
money.val
:Da wir keine Listener dafür definiert haben, passiert nach
money.val
Änderungen an 2 nichts Besonderes .Definieren wir nun einige Listener. Wir haben vier Hörer zur Verfügung:
beforeSet
,beforeChange
,afterChange
,afterSet
. Folgendes geschieht nacheinander, wenn Siemoney.val = newValue
den Wert der Variablen ändern:Jetzt definieren wir den
afterChange
Listener, der erst ausgelöst wird, nachdem ermoney.val
sich geändert hat (währendafterSet
er ausgelöst wird, auch wenn der neue Wert mit dem alten identisch ist):Stellen Sie nun einen neuen Wert ein
3
und sehen Sie, was passiert:In der Konsole wird Folgendes angezeigt:
Den vollständigen Code finden Sie unter https://gist.github.com/yusanshi/65745acd23c8587236c50e54f25731ab .
quelle
Dies ist ein alter Thread, aber ich bin auf die zweithöchste Antwort gestoßen (benutzerdefinierte Listener), als ich nach einer Lösung mit Angular gesucht habe. Während die Lösung funktioniert, verfügt Angular über eine bessere integrierte Methode, um dieses Problem mithilfe von
@Output
und Ereignisemittenten zu beheben . Verlassen Sie das Beispiel in der benutzerdefinierten Listener-Antwort:ChildComponent.html
ChildComponent.ts
ParentComponent.html
ParentComponent.ts
Dies wird nun
n
bei jedem Klicken auf die untergeordnete Schaltfläche auf dem übergeordneten Element aktualisiert . Arbeits stackblitzquelle
quelle