Czy możliwe jest zdarzenie w JS, które jest uruchamiane, gdy zmienia się wartość określonej zmiennej? JQuery jest akceptowane.
javascript
jquery
dom-events
rashcroft22
źródło
źródło
variable
, ale wszystkie odpowiedzi tutaj odnoszą sięproperty
. Zastanawiam się jednak, czy możemy nasłuchiwaćlocal variable
zmian.Odpowiedzi:
Tak, jest to teraz całkowicie możliwe!
Wiem, że to stary wątek, ale teraz ten efekt jest możliwy przy użyciu akcesoriów (pobierających i ustawiających): https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Working_with_Objects#Defining_getters_and_setters
Możesz zdefiniować taki obiekt, w którym
aInternal
reprezentuje polea
:Następnie możesz zarejestrować słuchacza za pomocą:
Tak więc, gdy cokolwiek zmieni wartość
x.a
, funkcja nasłuchiwania zostanie uruchomiona. Uruchomienie następującego wiersza spowoduje wyświetlenie wyskakującego powiadomienia:Zobacz przykład tutaj: https://jsfiddle.net/5o1wf1bn/1/
Możesz także użyć tablicy słuchaczy zamiast jednego gniazda słuchacza, ale chciałem dać ci najprostszy możliwy przykład.
źródło
this.aListener(val)
, będziesz musiał przeglądać wszystkie funkcje nasłuchiwania i wywoływać każde z nichval
. Zazwyczaj metoda jest wywoływanaaddListener
zamiastregisterListener
.Większość odpowiedzi na to pytanie jest przestarzała, nieskuteczna lub wymaga włączenia dużych, rozdętych bibliotek:
Obecnie możesz teraz używać obiektu Proxy do monitorowania (i przechwytywania) zmian wprowadzonych w obiekcie. Jest przeznaczony do tego, co OP chce zrobić. Oto podstawowy przykład:
Jedynymi wadami
Proxy
obiektu są:Proxy
Obiekt nie jest dostępny w starszych przeglądarek (takich jak IE11) oraz polyfill nie może w pełni kopiąProxy
funkcjonalności.Date
) -Proxy
najlepiej połączyć obiekt ze zwykłymi obiektami lub tablicami.Jeśli chcesz obserwować zmiany dokonane w zagnieżdżonym obiekcie , musisz użyć specjalistycznej biblioteki, takiej jak Observable Slim (którą opublikowałem), która działa w następujący sposób:
źródło
target.hello_world = "test"
)you don't actually watch changes on the target object but only on proxy object
- to nie do końca dokładne.Proxy
Obiekt nie jest modyfikowany - nie mieć swój własny egzemplarz cel.you just want to know when a property change on the target object
- możesz to zrobić za pomocąProxy
, jest to jeden z głównych przypadków użycia serwerów proxy.target
, musisz to zrobić przez proxy. Nieproxy.hello_world = "test"
oznacza to jednak, że modyfikujesz serwer proxy, serwer proxy pozostaje niezmieniony,target
zostaje zmodyfikowany (jeśli Twój program obsługi jest skonfigurowany do tego). Wygląda na to, że Twoim celem jest to, że nie możesz bezpośrednio obserwowaćtarget.hello_world = "test"
. To prawda. Zwykłe przypisania zmiennych nie emitują żadnego zdarzenia. Dlatego musimy korzystać z narzędzi takich jak te opisane w odpowiedziach na to pytanie.It sounds like your point is that you cannot directly observe target.hello_world = "test". That is true.
o to mi chodzi. W moim przypadku mam obiekt utworzony gdzieś indziej i zaktualizowany przez inny kod ... proxy w tym przypadku nie jest przydatne, ponieważ zmiany zostaną wprowadzone w celu.Nie.
Ale jeśli to naprawdę tak ważne, masz 2 opcje (pierwsza jest testowana, druga nie):
Najpierw użyj seterów i getterów, takich jak:
możesz zrobić coś takiego:
następnie ustaw detektor w następujący sposób:
Po drugie, właściwie zapomniałem, prześlę się, gdy się nad tym zastanowię :)
EDYCJA: Och, pamiętam :) Możesz postawić zegarek na wartość:
Biorąc pod uwagę myobj powyżej, z „a” na nim:
źródło
Korzystanie
Prototype
: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/definePropertyInny przykład
źródło
varw
wymaga 2 argumentów, ale część twojego przykładu pokazuje, że funkcja jest wywoływana tylko z parametrem value.Przykro mi, że przywołałem stary wątek, ale oto mała instrukcja dla tych, którzy (jak ja!) Nie widzą, jak działa przykład Eli Grey:
Mam nadzieję, że to może komuś pomóc
źródło
Jako odpowiedź Luke'a Schafera ( uwaga : odnosi się to do jego oryginalnego postu, ale cały punkt tutaj pozostaje ważny po edycji ), sugerowałbym również parę metod Get / Set, aby uzyskać dostęp do twojej wartości.
Sugerowałbym jednak pewne modyfikacje (i dlatego publikuję ...).
Problem z tym kodem polega na tym, że pole
a
obiektumyobj
jest bezpośrednio dostępne, więc można uzyskać do niego dostęp / zmienić jego wartość bez wyzwalania detektorów:Kapsułkowanie
Tak więc, aby zagwarantować, że słuchacze są faktycznie wezwani, musielibyśmy zabronić tego bezpośredniego dostępu do pola
a
. Jak to zrobić? Użyj zamknięcia !Teraz możesz użyć tej samej metody do tworzenia i dodawania słuchaczy, jak zaproponował Luke, ale możesz być pewny, że nie ma możliwości, aby czytać i pisać
a
niezauważone!Programowe dodawanie pól enkapsulowanych
Wciąż podążając śladem Luke'a, proponuję teraz prosty sposób dodawania do obiektów zamkniętych pól i odpowiednich modułów pobierających / ustawiających za pomocą prostego wywołania funkcji.
Pamiętaj, że będzie to działać poprawnie tylko z typami wartości . W tym celu do pracy z typami referencyjnymi , jakiś głęboki kopii musiałyby być realizowane (patrz ten jeden , na przykład).
Działa to tak samo jak poprzednio: tworzymy zmienną lokalną na funkcji, a następnie tworzymy zamknięcie.
Jak tego użyć? Prosty:
źródło
Jeśli używasz jQuery {UI} (z którego wszyscy powinni korzystać :-)), możesz użyć .change () z ukrytym elementem <input />.
źródło
<input/>
elementu?<input type="hidden" value="" id="thisOne" />
i jQuery$("#thisOne").change(function() { do stuff here });
i$("#thisOne").val(myVariableWhichIsNew);
, a następnie.change()
ogień.var1 = 'new value';
Zamiast tego ustawisz wartość tego ukrytego wejścia, a następnie dodasz detektor, aby zmienić zmienną.$("#val1").on('change', function(){ val1 = this.val(); ... do the stuff that you wanted to do when val1 changed... }); $("#val1").val('new value');
AngularJS
(Wiem, że tak nie jestJQuery
, ale to może pomóc. [Czysta JS jest dobra tylko w teorii]):gdzie „data” to nazwa zmiennej w zakresie.
Jest link do dokumentu.
źródło
$scope.$apply()
uruchomieniuDla tuningujących kilka lat później:
Dostępne jest rozwiązanie dla większości przeglądarek (i IE6 +), które wykorzystuje zdarzenie onpropertychange i nowszą specyfikację definProperty. Nieznaczny haczyk polega na tym, że musisz zmienić zmienną w obiekt dom.
Pełne szczegóły:
http://johndyer.name/native-browser-get-set-properties-in-javascript/
źródło
Funkcjonalności, której szukasz, można uzyskać za pomocą metody „replaceProperty ()” - dostępnej tylko w nowoczesnych przeglądarkach:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty
Napisałem rozszerzenie jQuery, które ma podobną funkcjonalność, jeśli potrzebujesz większej obsługi różnych przeglądarek:
https://github.com/jarederaj/jQueue
źródło
Nie bezpośrednio: potrzebujesz pary gettera / settera z interfejsem „addListener / removeListener” jakiegoś rodzaju ... lub wtyczki NPAPI (ale to zupełnie inna historia).
źródło
lub
lub
źródło
Dość prostym i uproszczonym rozwiązaniem jest po prostu użycie wywołania funkcji, aby ustawić wartość zmiennej globalnej i nigdy nie ustawiać jej bezpośrednio. W ten sposób masz całkowitą kontrolę:
Nie ma sposobu, aby to wymusić, wymaga jedynie dyscypliny programistycznej ... chociaż możesz użyć
grep
(lub czegoś podobnego), aby sprawdzić, czy nigdzie twój kod nie ustawia bezpośrednio wartościglobalVar
.Lub możesz zamknąć to w obiektach i metodach pobierania i ustawiania użytkownika ... tylko myśl.
źródło
var
w modułach ES6 - jest to jedyne rozwiązanie.Proszę, pamiętajcie, że początkowe pytanie dotyczyło ZMIENNYCH, a nie OBIEKTÓW;)
oprócz wszystkich powyższych odpowiedzi stworzyłem małą bibliotekę o nazwie forTheWatch.js , która używa tego samego sposobu do i wywoływania zmian w normalnych zmiennych globalnych w javascript.
Kompatybilny ze zmiennymi JQUERY, nie trzeba używać OBIEKTÓW, w razie potrzeby można przekazać bezpośrednio tablicę kilku zmiennych.
Jeśli to może być pomocne ...: https://bitbucket.org/esabora/forthewatch
Zasadniczo wystarczy wywołać funkcję:
watchIt("theVariableToWatch", "varChangedFunctionCallback");
I przepraszam z góry, jeśli nie dotyczy.
źródło
Najłatwiejszy sposób, jaki znalazłem, zaczynając od tej odpowiedzi :
I wtedy:
źródło
W moim przypadku próbowałem dowiedzieć się, czy jakakolwiek biblioteka, którą włączam do mojego projektu, redefiniuje moją
window.player
. Na początku mojego kodu po prostu:źródło
To nie jest bezpośrednio możliwe.
Można to jednak zrobić za pomocą CustomEvent: https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent
Poniższa metoda przyjmuje tablicę nazw zmiennych jako dane wejściowe i dodaje detektor zdarzeń dla każdej zmiennej i wyzwala zdarzenie w przypadku wszelkich zmian wartości zmiennych.
Metoda wykorzystuje odpytywanie w celu wykrycia zmiany wartości. Możesz zwiększyć wartość limitu czasu w milisekundach.
Wywołując metodę:
Wykryje zmiany w zmiennych nazwa użytkownika i identyfikator użytkownika.
źródło
Za pomocą gettera i settera możesz zdefiniować klasę JavaScript, która robi takie rzeczy.
Najpierw definiujemy naszą klasę o nazwie
MonitoredVariable
:Załóżmy, że chcemy nasłuchiwać
money
zmian, utwórzmy instancjęMonitoredVariable
z początkowymi pieniędzmi0
:Następnie możemy uzyskać lub ustawić jego wartość za pomocą
money.val
:Ponieważ nie zdefiniowaliśmy dla niego żadnych słuchaczy, po
money.val
zmianie na 2 nie dzieje się nic specjalnego .Teraz zdefiniujmy niektórych słuchaczy. Mamy cztery słuchaczy dostępny:
beforeSet
,beforeChange
,afterChange
,afterSet
. Następujące czynności będą się pojawiać sekwencyjnie, gdymoney.val = newValue
zmienisz wartość zmiennej:Teraz definiujemy
afterChange
nasłuchiwanie, które będzie uruchamiane dopiero pomoney.val
zmianie (podczas gdyafterSet
zostanie uruchomione, nawet jeśli nowa wartość jest taka sama jak stara):Teraz ustaw nową wartość
3
i zobacz, co się stanie:W konsoli zobaczysz następujące informacje:
Pełny kod można znaleźć na stronie https://gist.github.com/yusanshi/65745acd23c8587236c50e54f25731ab .
źródło
To jest stary wątek, ale natknąłem się na drugą najwyższą odpowiedź (niestandardowe odbiorniki), szukając rozwiązania za pomocą Angulara. Podczas gdy rozwiązanie działa, angular ma lepszą wbudowaną metodę rozwiązania tego problemu za pomocą
@Output
emiterów zdarzeń i zdarzeń. Wyjście z przykładu w niestandardowej odpowiedzi odbiornika:ChildComponent.html
ChildComponent.ts
ParentComponent.html
ParentComponent.ts
To będzie teraz aktualizować
n
nadrzędnie za każdym razem, gdy kliknięty zostanie przycisk potomny. Działający stackblitzźródło
źródło