Jadi sekarang HTML5 memperkenalkan history.pushState
untuk mengubah riwayat browser, situs web mulai menggunakan ini dalam kombinasi dengan Ajax alih-alih mengubah pengidentifikasi fragmen URL.
Sayangnya itu berarti bahwa panggilan tersebut tidak dapat dideteksi lagi oleh onhashchange
.
Pertanyaan saya adalah: Apakah ada cara yang dapat diandalkan (hack?;)) Untuk mendeteksi kapan situs web menggunakan history.pushState
? Spesifikasinya tidak menyatakan apa pun tentang peristiwa yang dimunculkan (setidaknya saya tidak dapat menemukan apa pun).
Saya mencoba membuat fasad dan diganti window.history
dengan objek JavaScript saya sendiri, tetapi tidak memiliki efek sama sekali.
Penjelasan lebih lanjut: Saya sedang mengembangkan add-on Firefox yang perlu mendeteksi perubahan ini dan bertindak sesuai.
Saya tahu ada pertanyaan serupa beberapa hari yang lalu yang menanyakan apakah mendengarkan beberapa acara DOM akan efisien tetapi saya lebih suka tidak mengandalkan itu karena peristiwa ini dapat dihasilkan karena banyak alasan berbeda.
Memperbarui:
Berikut ini adalah jsfiddle (gunakan Firefox 4 atau Chrome 8) yang menunjukkan bahwa onpopstate
tidak terpicu ketika pushState
dipanggil (atau saya melakukan sesuatu yang salah? Jangan ragu untuk memperbaikinya!).
Pembaruan 2:
Masalah (sisi) lain adalah yang window.location
tidak diperbarui saat menggunakan pushState
(tapi saya membaca tentang ini sudah ada di sini pada SO saya pikir).
sumber
history
objek. Itu mungkin tidak perlu dalam kasus ini.window.history
hanya bisa dibaca tetapi properti dari objek sejarah tidak ... Terima kasih banyak untuk solusi ini :)pushState
metode asli untuk digunakan nanti. Jadi, alih-alih variabel global, saya memilih untuk merangkum seluruh kode menjadi IIFE: en.wikipedia.org/wiki/Immediately-invoked_function_expressionSaya menggunakan ini:
Ini hampir sama dengan galambalaz .
Tapi biasanya itu berlebihan. Dan itu mungkin tidak bekerja di semua browser. (Saya hanya peduli dengan versi browser saya.)
(Dan itu meninggalkan var
_wr
, jadi kamu mungkin ingin membungkusnya atau sesuatu. Aku tidak peduli tentang itu.)sumber
Akhirnya menemukan cara yang "benar" untuk melakukan ini! Perlu menambahkan hak istimewa untuk ekstensi Anda dan menggunakan halaman latar belakang (bukan hanya skrip konten), tetapi itu berfungsi.
Acara yang Anda inginkan adalah
browser.webNavigation.onHistoryStateUpdated
, yang dipecat ketika halaman menggunakanhistory
API untuk mengubah URL. Ini hanya diaktifkan untuk situs yang Anda memiliki izin untuk mengakses, dan Anda juga dapat menggunakan filter URL untuk lebih mengurangi spam jika Anda perlu. Ini memerlukanwebNavigation
izin (dan tentu saja izin host untuk domain yang relevan).Callback acara mendapatkan ID tab, URL yang sedang "dinavigasi", dan detail lainnya. Jika Anda perlu mengambil tindakan dalam skrip konten pada halaman tersebut saat acara dimulai, menyuntikkan skrip yang relevan langsung dari halaman latar belakang, atau meminta skrip konten membuka a
port
ke halaman latar belakang saat memuat, minta halaman latar disimpan port itu dalam koleksi yang diindeks oleh ID tab, dan mengirim pesan melintasi port yang relevan (dari skrip latar belakang ke skrip konten) saat acara diaktifkan.sumber
Anda dapat mengikat ke
window.onpopstate
acara tersebut?https://developer.mozilla.org/en/DOM%3awindow.onpopstate
Dari dokumen:
sumber
history.go
,.back
) fungsi dipanggil. Tapi tidakpushState
. Ini adalah usaha saya untuk mengujinya, mungkin saya melakukan sesuatu yang salah: jsfiddle.net/fkling/vV9vd Tampaknya hanya terkait dengan cara itu bahwa jika sejarah diubah olehpushState
, objek keadaan terkait diteruskan ke event handler ketika metode lain disebut.Karena Anda bertanya tentang addon Firefox, inilah kode yang harus saya gunakan. Menggunakan
unsafeWindow
ini tidak lagi direkomendasikan , dan kesalahan ketika pushState dipanggil dari script klien setelah dimodifikasi:Sebagai gantinya, ada API yang disebut exportFunction yang memungkinkan fungsi untuk disuntikkan ke dalam
window.history
seperti ini:sumber
unsafeWindow.history,
kewindow.history
. Itu tidak bekerja untuk saya dengan Windows tidak aman.jawaban monyet galambalazs
window.history.pushState
danwindow.history.replaceState
, tetapi untuk beberapa alasan berhenti bekerja untuk saya. Inilah alternatif yang tidak sebaik karena menggunakan polling:sumber
Saya pikir topik ini membutuhkan solusi yang lebih modern.
Saya yakin
nsIWebProgressListener
ada sekitar saat itu saya terkejut tidak ada yang menyebutkannya.Dari sebuah skrip frame (untuk kompatibilitas e10s):
Kemudian mendengarkan di
onLoacationChange
Itu tampaknya akan menangkap semua pushState. Tetapi ada peringatan komentar bahwa itu "JUGA memicu untuk pushState". Jadi kita perlu melakukan lebih banyak penyaringan di sini untuk memastikan itu hanya hal-hal pushstate.
Berdasarkan pada: https://github.com/jgraham/gecko/blob/55d8d9aa7311386ee2dabfccb481684c8920a527/toolkit/modules/addons/WebNavigation.jsm#L18
Dan: sumber daya: //gre/modules/WebNavigationContent.js
sumber
Yah, saya melihat banyak contoh untuk mengganti
pushState
propertihistory
tetapi saya tidak yakin itu ide yang bagus, saya lebih suka untuk membuat acara layanan berbasis dengan API yang mirip dengan sejarah dengan cara itu Anda dapat mengontrol tidak hanya push state tetapi ganti state juga dan itu membuka pintu bagi banyak implementasi lainnya yang tidak mengandalkan API sejarah global. Silakan periksa contoh berikut:Jika Anda memerlukan
EventEmitter
definisi, kode di atas didasarkan pada emitor acara NodeJS: https://github.com/nodejs/node/blob/36732084db9d0ff59b6ce31e839450cd91a156be/lib/events.js .utils.inherits
implementasi dapat ditemukan di sini: https://github.com/nodejs/node/blob/36732084db9d0ff59b6ce31e839450cd91a156be/lib/util.js#L970sumber
Saya lebih suka tidak menimpa metode sejarah asli sehingga implementasi sederhana ini membuat fungsi saya sendiri yang disebut stateedPush state yang hanya mengirimkan suatu peristiwa dan mengembalikan history.pushState (). Either way berfungsi dengan baik tetapi saya menemukan implementasi ini sedikit lebih bersih karena metode asli akan terus berkinerja seperti yang diharapkan pengembang di masa depan.
sumber
Berdasarkan solusi yang diberikan oleh @gblazex , jika Anda ingin mengikuti pendekatan yang sama, tetapi menggunakan fungsi panah, ikuti contoh di bawah ini dalam logika javascript Anda:
Kemudian, terapkan fungsi lain
_notifyUrl(url)
yang memicu tindakan apa pun yang diperlukan yang mungkin Anda perlukan saat url halaman saat ini diperbarui (bahkan jika halaman belum dimuat sama sekali)sumber
Karena saya hanya menginginkan URL baru, saya telah mengadaptasi kode @gblazex dan @Alberto S. untuk mendapatkan ini:
sumber
Saya tidak berpikir itu ide yang baik untuk memodifikasi fungsi asli bahkan jika Anda bisa, dan Anda harus selalu menjaga ruang lingkup aplikasi Anda, jadi pendekatan yang baik tidak menggunakan fungsi pushState global, sebaliknya, gunakan salah satu dari Anda sendiri:
Perhatikan bahwa jika ada kode lain yang menggunakan fungsi pushState asli, Anda tidak akan mendapatkan pemicu acara (tetapi jika ini terjadi, Anda harus memeriksa kode Anda)
sumber
Sebagai negara standar:
kita perlu memanggil history.back () ke trigeer WindowEventHandlers.onpopstate
Jadi insted dari:
melakukan:
sumber