Apakah mungkin untuk memiliki acara di JS yang menyala ketika nilai variabel tertentu berubah? JQuery diterima.
javascript
jquery
dom-events
rashcroft22
sumber
sumber
variable
, namun semua jawaban di sini merujukproperty
. Saya ingin tahu apakah kita dapat mendengarkanlocal variable
perubahan.Jawaban:
Ya, ini sekarang sangat mungkin!
Saya tahu ini adalah utas lama tetapi sekarang efek ini dimungkinkan menggunakan pengakses (getter dan setter): https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Working_with_Objects#Defining_getters_and_setters
Anda bisa mendefinisikan objek seperti ini, yang
aInternal
mewakili bidanga
:Kemudian Anda dapat mendaftarkan pendengar menggunakan yang berikut:
Jadi, setiap kali ada perubahan nilai
x.a
, fungsi pendengar akan diaktifkan. Menjalankan baris berikut akan memunculkan popup peringatan:Lihat contoh di sini: https://jsfiddle.net/5o1wf1bn/1/
Anda juga dapat menggunakan array pendengar alih-alih slot pendengar tunggal, tapi saya ingin memberi Anda contoh paling sederhana.
sumber
this.aListener(val)
, Anda harus mengulang semua fungsi pendengar dan memanggil masing-masing lewatval
. Biasanya, metode ini disebutaddListener
bukanregisterListener
.Sebagian besar jawaban untuk pertanyaan ini sudah usang, tidak efektif, atau memerlukan dimasukkannya perpustakaan besar yang membengkak:
Hari ini, Anda sekarang dapat menggunakan objek Proxy untuk memantau (dan mencegat) perubahan yang dilakukan pada suatu objek. Ini adalah tujuan yang dibangun untuk apa yang OP coba lakukan. Inilah contoh dasar:
Satu-satunya kelemahan
Proxy
objek adalah:Proxy
objek tidak tersedia di browser lama (seperti IE11) dan polyfill tidak bisa sepenuhnya meniruProxy
fungsi.Date
) -Proxy
objek paling baik dipasangkan dengan Objek atau Array.Jika Anda perlu mengamati perubahan yang dilakukan pada objek bersarang , maka Anda perlu menggunakan perpustakaan khusus seperti Observable Slim (yang telah saya terbitkan) yang berfungsi seperti ini:
sumber
target.hello_world = "test"
)you don't actually watch changes on the target object but only on proxy object
- itu tidak cukup akurat. TheProxy
objek tidak dimodifikasi - itu tidak memiliki salinan itu sendiri dari target.you just want to know when a property change on the target object
- Anda dapat mencapainya denganProxy
, itu salah satu kasus penggunaan utama untuk proxy.target
, maka Anda harus melakukannya melalui proxy. Namunproxy.hello_world = "test"
tidak berarti Anda memodifikasi proxy, proxy tetap tidak berubah,target
akan dimodifikasi (jika set handler Anda dikonfigurasi untuk melakukannya). Sepertinya poin Anda adalah bahwa Anda tidak dapat mengamati secara langsungtarget.hello_world = "test"
. Itu benar. Tugas variabel biasa tidak memancarkan jenis acara apa pun. Itu sebabnya kita harus menggunakan alat seperti yang dijelaskan dalam jawaban untuk pertanyaan ini.It sounds like your point is that you cannot directly observe target.hello_world = "test". That is true.
itu maksud saya. Dalam kasus saya, saya memiliki objek yang dibuat di tempat lain dan telah diperbarui oleh beberapa kode lain ... proxy, dalam hal ini, tidak berguna karena perubahan akan dilakukan pada target.Tidak.
Tapi, jika itu benar-benar penting, Anda memiliki 2 opsi (pertama diuji, kedua tidak):
Pertama, gunakan setter dan getter, seperti:
maka Anda dapat melakukan sesuatu seperti:
kemudian atur pendengar seperti:
Kedua, saya benar-benar lupa, saya akan serahkan sementara saya memikirkannya :)
EDIT: Oh, saya ingat :) Anda bisa memberi nilai pada jam tangan:
Diberikan myobj di atas, dengan 'a' di atasnya:
sumber
Menggunakan
Prototype
: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/definePropertyContoh lainnya
sumber
varw
membutuhkan 2 argumen tetapi bagian dari contoh Anda menunjukkan fungsi dipanggil hanya dengan parameter nilai.Maaf untuk membuka utas lama, tetapi di sini ada manual kecil bagi mereka yang (seperti saya!) Tidak melihat bagaimana contoh kerja Eli Grey:
Semoga ini bisa membantu seseorang
sumber
Sebagai jawaban Luke Schafer ( catatan : ini merujuk pada posting aslinya; tetapi seluruh poin di sini tetap valid setelah diedit ), saya juga menyarankan sepasang metode Get / Set untuk mengakses nilai Anda.
Namun saya akan menyarankan beberapa modifikasi (dan itulah sebabnya saya memposting ...).
Masalah dengan kode itu adalah bahwa bidang
a
objekmyobj
dapat diakses secara langsung, sehingga dimungkinkan untuk mengaksesnya / mengubah nilainya tanpa memicu pendengar:Enkapsulasi
Jadi, untuk menjamin bahwa pendengar benar-benar dipanggil, kita harus melarang akses langsung ke lapangan
a
. Bagaimana cara melakukannya? Gunakan penutupan !Sekarang Anda dapat menggunakan metode yang sama untuk membuat dan menambahkan pendengar seperti yang diusulkan Luke, tetapi Anda dapat yakin bahwa tidak ada cara yang mungkin untuk membaca atau menulis agar
a
tidak diperhatikan!Menambahkan bidang enkapsulasi secara pemrograman
Masih di jalur Luke, sekarang saya usulkan cara sederhana untuk menambahkan bidang enkapsulasi dan masing-masing getter / setter ke objek dengan cara pemanggilan fungsi sederhana.
Perhatikan bahwa ini hanya akan berfungsi dengan baik dengan tipe nilai . Agar ini bekerja dengan tipe referensi , beberapa jenis salinan yang dalam harus diimplementasikan (lihat yang ini , misalnya).
Ini berfungsi sama seperti sebelumnya: kita membuat variabel lokal pada suatu fungsi, dan kemudian kita membuat penutupan.
Bagaimana cara menggunakannya? Sederhana:
sumber
Jika Anda menggunakan jQuery {UI} (yang harus digunakan semua orang :-)), Anda dapat menggunakan .change () dengan elemen <input /> tersembunyi.
sumber
<input/>
elemen tersembunyi ?<input type="hidden" value="" id="thisOne" />
dan dengan jQuery$("#thisOne").change(function() { do stuff here });
dan$("#thisOne").val(myVariableWhichIsNew);
dan kemudian.change()
akan api.var1 = 'new value';
, Anda malah akan menetapkan nilai input tersembunyi ini, lalu menambahkan pendengar untuk mengubah variabel.$("#val1").on('change', function(){ val1 = this.val(); ... do the stuff that you wanted to do when val1 changed... }); $("#val1").val('new value');
AngularJS
(Saya tahu ini bukanJQuery
, tapi itu mungkin bisa membantu. [JS Murni hanya baik secara teori]):di mana "data" adalah nama variabel Anda dalam cakupan.
Ada tautan ke doc.
sumber
$scope.$apply()
dijalankanUntuk penyetelan beberapa tahun kemudian:
Sebuah solusi untuk sebagian besar browser (dan IE6 +) tersedia yang menggunakan event onpropertychange dan spec defineProperty yang lebih baru. Tangkapan kecil adalah bahwa Anda harus membuat variabel Anda objek dom.
Detail lengkap:
http://johndyer.name/native-browser-get-set-properties-in-javascript/
sumber
Fungsionalitas yang Anda cari dapat dicapai melalui penggunaan metode "defineProperty ()" - yang hanya tersedia untuk browser modern:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty
Saya telah menulis ekstensi jQuery yang memiliki beberapa fungsi serupa jika Anda memerlukan lebih banyak dukungan lintas browser:
https://github.com/jarederaj/jQueue
sumber
Tidak secara langsung: Anda memerlukan sepasang pengambil / penyetel dengan antarmuka "addListener / removeListener" semacam ... atau sebuah plugin NPAPI (tapi itu cerita lain sama sekali).
sumber
atau
atau
sumber
Solusi yang agak sederhana dan sederhana adalah dengan hanya menggunakan pemanggilan fungsi untuk mengatur nilai variabel global, dan tidak pernah menetapkan nilainya secara langsung. Dengan cara ini Anda memiliki kontrol total:
Tidak ada cara untuk menegakkan ini, itu hanya membutuhkan disiplin pemrograman ... meskipun Anda dapat menggunakan
grep
(atau sesuatu yang serupa) untuk memeriksa bahwa tidak ada kode yang langsung mengatur nilaiglobalVar
.Atau Anda bisa merangkumnya dalam objek dan metode pengambil dan penyetel pengguna ... hanya pemikiran.
sumber
var
dalam modul ES6 - ini adalah satu - satunya solusi.Tolong ingat pertanyaan awal adalah untuk VARIABEL, bukan untuk BENDA;)
selain semua jawaban di atas, saya membuat lib kecil bernama forTheWatch.js , yang menggunakan cara yang sama untuk menangkap dan balik untuk perubahan dalam variabel global normal dalam javascript.
Kompatibel dengan variabel JQUERY, tidak perlu menggunakan OBYEK, dan Anda dapat melewati secara langsung ARRAY dari beberapa variabel jika diperlukan.
Jika ini bisa membantu ...: https://bitbucket.org/esabora/forthewatch
Pada dasarnya Anda hanya perlu memanggil fungsi:
watchIt("theVariableToWatch", "varChangedFunctionCallback");
Dan maaf sebelumnya jika tidak relevan.
sumber
Cara termudah yang saya temukan, mulai dari jawaban ini :
Lalu:
sumber
Dalam kasus saya, saya mencoba mencari tahu apakah ada perpustakaan yang saya masukkan dalam proyek saya yang mendefinisikan ulang perpustakaan saya
window.player
. Jadi, pada awal kode saya, saya baru saja melakukannya:sumber
Itu tidak mungkin secara langsung.
Namun, ini dapat dilakukan dengan menggunakan CustomEvent: https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent
Metode di bawah ini menerima array nama variabel sebagai input dan menambahkan pendengar acara untuk setiap variabel dan memicu acara untuk setiap perubahan pada nilai variabel.
Metode menggunakan polling untuk mendeteksi perubahan nilai. Anda dapat meningkatkan nilai waktu habis dalam milidetik.
Dengan memanggil Metode:
Ini akan mendeteksi perubahan pada variabel username dan userid.
sumber
Dengan bantuan pengambil dan penyetel , Anda dapat menentukan kelas JavaScript yang melakukan hal seperti itu.
Pertama, kita mendefinisikan kelas kita yang disebut
MonitoredVariable
:Anggap kita ingin mendengarkan
money
perubahan, mari kita membuat contohMonitoredVariable
dengan uang awal0
:Lalu kita bisa mendapatkan atau mengatur nilainya menggunakan
money.val
:Karena kami belum menetapkan pendengar untuk itu, tidak ada yang istimewa terjadi setelah
money.val
perubahan ke 2.Sekarang mari kita mendefinisikan beberapa pendengar. Kami memiliki empat pendengar yang tersedia:
beforeSet
,beforeChange
,afterChange
,afterSet
. Berikut ini akan terjadi secara berurutan ketika Anda digunakanmoney.val = newValue
untuk mengubah nilai variabel:Sekarang kita mendefinisikan
afterChange
pendengar yang dipicu hanya setelahmoney.val
telah berubah (sementaraafterSet
akan dipicu bahkan jika nilai baru sama dengan yang lama):Sekarang tetapkan nilai baru
3
dan lihat apa yang terjadi:Anda akan melihat yang berikut di konsol:
Untuk kode lengkap, lihat https://gist.github.com/yusanshi/65745acd23c8587236c50e54f25731ab .
sumber
Ini adalah utas lama tapi saya menemukan jawaban tertinggi kedua (pendengar khusus) sambil mencari solusi menggunakan Angular. Sementara solusinya bekerja, angular memiliki cara yang lebih baik untuk menyelesaikan penggunaan
@Output
dan pemancar acara ini. Keluar dari contoh dalam jawaban pendengar khusus:ChildComponent.html
ChildComponent.ts
ParentComponent.html
ParentComponent.ts
Ini sekarang akan diperbarui
n
pada orang tua setiap kali tombol anak diklik. Bekerja stackblitzsumber
sumber