Apakah ada pendengar perubahan JavaScript / jQuery DOM?
402
Intinya saya ingin skrip dieksekusi ketika isi suatu DIVperubahan. Karena skrip terpisah (skrip konten dalam ekstensi Chrome & skrip halaman web), saya perlu cara mengamati perubahan dalam status DOM. Saya bisa mengatur pemungutan suara tetapi itu tampaknya ceroboh.
Untuk waktu yang lama, peristiwa mutasi DOM3 adalah solusi terbaik yang tersedia, tetapi mereka telah ditinggalkan karena alasan kinerja. Pengamat Mutasi DOM4 adalah pengganti untuk peristiwa mutasi DOM3 yang sudah usang. Mereka saat ini diimplementasikan di browser modern sebagai MutationObserver(atau sebagai awalan vendor WebKitMutationObserverdalam versi lama Chrome):
MutationObserver= window.MutationObserver|| window.WebKitMutationObserver;var observer =newMutationObserver(function(mutations, observer){// fired when a mutation occurs
console.log(mutations, observer);// ...});// define what element should be observed by the observer// and what types of mutations trigger the callback
observer.observe(document,{
subtree:true,
attributes:true//...});
Contoh ini mendengarkan perubahan DOM documentdan seluruh subtree-nya, dan itu akan diaktifkan pada perubahan atribut elemen serta perubahan struktural. Draf spesifikasi memiliki daftar lengkap properti pendengar mutasi yang valid :
childList
Tetapkan truejika mutasi ke anak-anak target harus diamati.
atribut
Setel ke trueapakah mutasi ke atribut target harus diamati.
characterData
Setel ke trueapakah mutasi ke data target harus diamati.
subtree
Tetapkan truejika mutasi tidak hanya untuk target, tetapi juga keturunan target harus diperhatikan.
atributOldValue
Setel ke truejika attributesdisetel ke true dan nilai atribut target sebelum mutasi perlu direkam.
characterDataOldValue
Setel ke truejika characterDatadisetel ke true dan data target sebelum mutasi perlu direkam.
atributFilter
Setel ke daftar nama lokal atribut (tanpa namespace) jika tidak semua mutasi atribut perlu diperhatikan.
(Daftar ini saat ini per April 2014; Anda dapat memeriksa spesifikasi untuk setiap perubahan.)
@AshrafBashir Saya melihat sampel berfungsi dengan baik di Firefox 19.0.2: Saya melihat ([{}])masuk ke konsol, yang menunjukkan yang diharapkan MutationRecordketika saya mengkliknya. Silakan periksa lagi, karena ini mungkin merupakan kegagalan teknis sementara di JSFiddle. Saya belum mengujinya di IE, karena saya tidak punya IE 10, yang saat ini satu-satunya versi untuk mendukung peristiwa mutasi.
apsillers
1
Saya baru saja memposting jawaban yang berfungsi di IE10 + dan kebanyakan hal lain.
naugtur
1
Spesifikasi tampaknya tidak memiliki kotak hijau yang mencantumkan opsi pengamat mutasi lebih lama. Itu daftar opsi di bagian 5.3.1 dan menjelaskan mereka hanya sedikit lebih jauh di bawah itu.
LS
2
@LS Terima kasih, saya telah memperbarui tautan, menghapus sedikit tentang kotak hijau, dan mengedit seluruh daftar menjadi jawaban saya (kalau-kalau membusuk tautan di masa depan).
Jawaban ini sekarang sudah usang. Lihat jawabannya oleh apsillers .
Karena ini untuk ekstensi Chrome, Anda sebaiknya menggunakan acara DOM standar - DOMSubtreeModified. Lihat dukungan untuk acara ini di seluruh browser. Itu telah didukung di Chrome sejak 1.0.
Masih berfungsi jika Anda sedang membangun ekstensi chrome. tak ternilai.
concept47
49
Banyak situs menggunakan AJAX untuk menambah / menampilkan / mengubah konten secara dinamis. Kadang-kadang digunakan alih-alih navigasi di dalam situs, sehingga URL saat ini diubah secara terprogram dan skrip konten tidak secara otomatis dijalankan oleh browser dalam hal ini karena halaman tersebut tidak diambil dari server jauh sepenuhnya.
Metode JS biasa mendeteksi perubahan halaman yang tersedia dalam skrip konten .
MutationObserver ( docs ) untuk mendeteksi perubahan DOM:
Pengecekan DOM secara berkala melalui setInterval :
Jelas ini hanya akan berfungsi jika Anda menunggu elemen tertentu yang diidentifikasi oleh id / pemilihnya muncul, dan itu tidak akan membiarkan Anda secara universal mendeteksi konten yang ditambahkan secara dinamis baru kecuali jika Anda menemukan semacam sidik jari isi yang ada.
document.head.appendChild(document.createElement('script')).text ='('+function(){// injected DOM script is not a content script anymore, // it can modify objects and functions of the pagevar _pushState = history.pushState;
history.pushState =function(state, title, url){
_pushState.call(this, state, title, url);
window.dispatchEvent(newCustomEvent('state-changed',{detail: state}));};// repeat the above for replaceState too}+')(); this.remove();';// remove the DOM script element// And here content script listens to our DOM script custom events
window.addEventListener('state-changed',function(e){
console.log('History state changed', e.detail, location.hash);
doSomething();});
Pendekatan lain tergantung pada bagaimana Anda mengubah div. Jika Anda menggunakan JQuery untuk mengubah konten div dengan metode html (), Anda dapat memperluas metode itu dan memanggil fungsi registrasi setiap kali Anda memasukkan html ke div.
(function( $, oldHtmlMethod ){// Override the core html method in the jQuery object.
$.fn.html =function(){// Execute the original HTML method using the// augmented arguments collection.var results = oldHtmlMethod.apply(this, arguments );
com.invisibility.elements.findAndRegisterElements(this);return results;};})( jQuery, jQuery.fn.html );
Kami hanya mencegat panggilan ke html (), memanggil fungsi pendaftaran dengan ini, yang dalam konteksnya merujuk pada elemen target mendapatkan konten baru, kemudian kami meneruskan panggilan ke fungsi jquery.html () asli. Ingatlah untuk mengembalikan hasil metode html () asli, karena JQuery mengharapkannya untuk metode chaining.
Selain alat "mentah" yang disediakan oleh MutationObserverAPI , ada pustaka "kenyamanan" untuk bekerja dengan mutasi DOM.
Pertimbangkan: MutationObserver mewakili setiap perubahan DOM dalam hal subtrees. Jadi, jika Anda, misalnya, menunggu elemen tertentu dimasukkan, itu mungkin jauh di dalam diri anak-anakmutations.mutation[i].addedNodes[j] .
Masalah lain adalah ketika kode Anda sendiri, sebagai reaksi terhadap mutasi, mengubah DOM - Anda sering ingin memfilternya.
Perpustakaan kenyamanan yang baik yang memecahkan masalah tersebut adalah mutation-summary (penafian: Saya bukan pembuatnya, hanya pengguna yang puas), yang memungkinkan Anda menentukan pertanyaan dari apa yang Anda minati, dan mendapatkan persisnya.
([{}])
masuk ke konsol, yang menunjukkan yang diharapkanMutationRecord
ketika saya mengkliknya. Silakan periksa lagi, karena ini mungkin merupakan kegagalan teknis sementara di JSFiddle. Saya belum mengujinya di IE, karena saya tidak punya IE 10, yang saat ini satu-satunya versi untuk mendukung peristiwa mutasi.Edit
Jawaban ini sekarang sudah usang. Lihat jawabannya oleh apsillers .
Karena ini untuk ekstensi Chrome, Anda sebaiknya menggunakan acara DOM standar -
DOMSubtreeModified
. Lihat dukungan untuk acara ini di seluruh browser. Itu telah didukung di Chrome sejak 1.0.Lihat contoh yang berfungsi di sini .
sumber
Banyak situs menggunakan AJAX untuk menambah / menampilkan / mengubah konten secara dinamis. Kadang-kadang digunakan alih-alih navigasi di dalam situs, sehingga URL saat ini diubah secara terprogram dan skrip konten tidak secara otomatis dijalankan oleh browser dalam hal ini karena halaman tersebut tidak diambil dari server jauh sepenuhnya.
Metode JS biasa mendeteksi perubahan halaman yang tersedia dalam skrip konten .
MutationObserver ( docs ) untuk mendeteksi perubahan DOM:
Pendengar acara untuk situs yang memberi sinyal perubahan konten dengan mengirim acara DOM:
pjax:end
padadocument
digunakan oleh banyak situs berbasis pjax misalnya GitHub,lihat Bagaimana menjalankan jQuery sebelum dan sesudah memuat pjax?
message
padawindow
digunakan oleh misalnya pencarian Google di browser Chrome,lihat ekstensi Chrome mendeteksi refresh pencarian Google
spfdone
saatdocument
digunakan oleh Youtube,lihat Bagaimana cara mendeteksi navigasi halaman di Youtube dan memodifikasi HTML sebelum halaman diberikan?
Pengecekan DOM secara berkala melalui setInterval :
Jelas ini hanya akan berfungsi jika Anda menunggu elemen tertentu yang diidentifikasi oleh id / pemilihnya muncul, dan itu tidak akan membiarkan Anda secara universal mendeteksi konten yang ditambahkan secara dinamis baru kecuali jika Anda menemukan semacam sidik jari isi yang ada.
Cloaking History API di dalam skrip DOM yang disuntikkan :
Mendengarkan hashchange , popstate events:
Khusus ekstensi: mendeteksi perubahan URL di latar belakang / halaman acara .
Ada API canggih untuk bekerja dengan navigasi: navigasi web , webRequest , tetapi kami akan menggunakan chrome.tabs.onUpdated pendengar acara sederhana yang mengirim pesan ke skrip konten:
manifest.json:
menyatakan latar belakang / halaman acara
menyatakan skrip konten
menambahkan
"tabs"
izin .background.js
content.js
sumber
Pendekatan lain tergantung pada bagaimana Anda mengubah div. Jika Anda menggunakan JQuery untuk mengubah konten div dengan metode html (), Anda dapat memperluas metode itu dan memanggil fungsi registrasi setiap kali Anda memasukkan html ke div.
Kami hanya mencegat panggilan ke html (), memanggil fungsi pendaftaran dengan ini, yang dalam konteksnya merujuk pada elemen target mendapatkan konten baru, kemudian kami meneruskan panggilan ke fungsi jquery.html () asli. Ingatlah untuk mengembalikan hasil metode html () asli, karena JQuery mengharapkannya untuk metode chaining.
Untuk info lebih lanjut tentang metode overriding dan ekstensi, lihat http://www.bennadel.com/blog/2009-Using-Self-Executing-Function-Arguments-To-Override-Core-jQuery-Methods.htm , di mana Saya menuliskan fungsi penutupan. Lihat juga tutorial plugin di situs JQuery.
sumber
Selain alat "mentah" yang disediakan oleh
MutationObserver
API , ada pustaka "kenyamanan" untuk bekerja dengan mutasi DOM.Pertimbangkan: MutationObserver mewakili setiap perubahan DOM dalam hal subtrees. Jadi, jika Anda, misalnya, menunggu elemen tertentu dimasukkan, itu mungkin jauh di dalam diri anak-anak
mutations.mutation[i].addedNodes[j]
.Masalah lain adalah ketika kode Anda sendiri, sebagai reaksi terhadap mutasi, mengubah DOM - Anda sering ingin memfilternya.
Perpustakaan kenyamanan yang baik yang memecahkan masalah tersebut adalah
mutation-summary
(penafian: Saya bukan pembuatnya, hanya pengguna yang puas), yang memungkinkan Anda menentukan pertanyaan dari apa yang Anda minati, dan mendapatkan persisnya.Contoh penggunaan dasar dari dokumen:
sumber