Saya menggunakan History API untuk aplikasi web saya dan memiliki satu masalah. Saya melakukan panggilan Ajax untuk memperbarui beberapa hasil pada halaman dan menggunakan history.pushState () untuk memperbarui bilah lokasi browser tanpa memuat ulang halaman. Kemudian, tentu saja, saya menggunakan window.popstate untuk mengembalikan keadaan sebelumnya saat tombol kembali diklik.
Masalahnya sudah diketahui - Chrome dan Firefox memperlakukan acara popstate itu secara berbeda. Meskipun Firefox tidak mengaktifkannya pada pemuatan pertama, Chrome melakukannya. Saya ingin memiliki gaya Firefox dan tidak mengaktifkan acara saat dimuat karena ini hanya memperbarui hasil dengan hasil yang persis sama saat dimuat. Apakah ada solusi selain menggunakan History.js ? Alasan saya tidak ingin menggunakannya adalah - ini membutuhkan terlalu banyak pustaka JS dengan sendirinya dan, karena saya membutuhkannya untuk diimplementasikan dalam CMS dengan JS yang sudah terlalu banyak, saya ingin meminimalkan JS yang saya masukkan ke dalamnya .
Jadi, ingin tahu apakah ada cara untuk membuat Chrome tidak menjalankan 'popstate' saat dimuat atau, mungkin, seseorang mencoba menggunakan History.js karena semua pustaka digabungkan menjadi satu file.
Jawaban:
Di Google Chrome versi 19, solusi dari @spliter berhenti bekerja. Seperti yang ditunjukkan @johnnymire, history.state di Chrome 19 ada, tetapi null.
Solusi saya adalah menambahkan window.history.state! == null untuk memeriksa apakah status ada di window.history:
Saya mengujinya di semua browser utama dan di Chrome versi 19 dan 18. Sepertinya berhasil.
sumber
in
dannull
memeriksa hanya!= null
karena itu akan mengurusnyaundefined
juga.null
dalamhistory.pushState()
metode sepertihistory.pushState(null,null,'http//example.com/)
. Memang, itu mungkin sebagian besar penggunaan (begitulah cara menyiapkannya di jquery.pjax.js dan sebagian besar demo lainnya). Tetapi jika browser mengimplementasikanwindow.history.state
(seperti FF dan Chrome 19+), window.history.state bisa menjadi non-null saat penyegaran atau setelah browser dimulai ulangJika Anda tidak ingin mengambil tindakan khusus untuk setiap penangan yang Anda tambahkan ke onpopstate, solusi saya mungkin menarik untuk Anda. Nilai tambah yang besar dari solusi ini juga bahwa event onpopstate dapat ditangani sebelum pemuatan halaman selesai.
Jalankan saja kode ini sekali sebelum Anda menambahkan penangan onpopstate dan semuanya akan bekerja seperti yang diharapkan (alias seperti di Mozilla ^^) .
Bagaimana itu bekerja:
Chrome, Safari dan mungkin browser webkit lainnya mengaktifkan acara onpopstate saat dokumen telah dimuat. Ini tidak dimaksudkan, jadi kami memblokir event popstate hingga event loop pertama setelah dokumen dimuat. Ini dilakukan oleh panggilan preventDefault dan stopImmediatePropagation (tidak seperti stopPropagation, stopImmediatePropagation menghentikan semua panggilan penangan peristiwa secara instan).Namun, karena readyState dokumen sudah "selesai" saat Chrome salah diaktifkan di popstate, kami mengizinkan peristiwa opopstate, yang telah diaktifkan sebelum pemuatan dokumen selesai untuk memungkinkan panggilan onpopstate sebelum dokumen dimuat.
Pembaruan 2014-04-23: Memperbaiki bug di mana acara popstate telah diblokir jika skrip dijalankan setelah halaman dimuat.
sumber
window.history.state
gagal memuat ulang jika status telah ditetapkan. Menyetel variabel sebelum kode clutters pushState. Solusi Anda elegan dan dapat ditempatkan di atas skrip lain, tanpa memengaruhi basis kode lainnya. Terima kasih.Menggunakan setTimeout saja bukanlah solusi yang tepat karena Anda tidak tahu berapa lama waktu yang dibutuhkan untuk konten dimuat sehingga mungkin kejadian popstate dipancarkan setelah batas waktu.
Inilah solusi saya: https://gist.github.com/3551566
sumber
Solusi telah ditemukan di jquery.pjax.js baris 195-225:
sumber
Solusi yang lebih langsung daripada menerapkan ulang pjax adalah menetapkan variabel di pushState, dan memeriksa variabel di popState, sehingga popState awal tidak aktif secara tidak konsisten saat dimuat (bukan solusi khusus jquery, hanya menggunakannya untuk acara):
sumber
window.history.ready
selalu benar.!window.history.ready && !ev.originalEvent.state
- kedua hal itu tidak pernah ditentukan saat saya menyegarkan laman. jadi karena itu tidak ada kode yang dieksekusi.Peristiwa onpopstate awal Webkit tidak memiliki status yang ditetapkan, jadi Anda dapat menggunakan ini untuk memeriksa perilaku yang tidak diinginkan:
Solusi komprehensif, yang memungkinkan navigasi kembali ke halaman asli, akan dibangun berdasarkan ide ini:
Meskipun ini masih dapat diaktifkan dua kali (dengan beberapa navigasi yang bagus), ini dapat ditangani hanya dengan memeriksa href sebelumnya.
sumber
window.history.state
juga null di iOS. Hanya memeriksa apakah properti e.state null sudah cukup.Ini adalah solusi saya.
sumber
Inilah solusi saya:
sumber
Cara terbaik agar Chrome tidak mengaktifkan popstate pada saat pemuatan halaman adalah dengan memilih-lebih https://code.google.com/p/chromium/issues/detail?id=63040 . Mereka tahu bahwa Chrome tidak mematuhi spesifikasi HTML5 selama dua tahun penuh sekarang dan masih belum memperbaikinya!
sumber
Jika digunakan,
event.state !== null
kembali ke riwayat ke halaman yang dimuat pertama tidak akan berfungsi di browser non seluler. Saya menggunakan sessionStorage untuk menandai kapan navigasi ajax benar-benar dimulai.sumber
Solusi yang disajikan memiliki masalah saat memuat ulang halaman. Berikut ini tampaknya berfungsi lebih baik, tetapi saya hanya menguji Firefox dan Chrome. Ini menggunakan aktualitas, bahwa tampaknya ada perbedaan antara
e.event.state
danwindow.history.state
.sumber
e.event
tidak ditentukanSaya tahu Anda bertanya untuk tidak melakukannya, tetapi Anda harus benar-benar menggunakan History.js karena menghapus jutaan inkompatibilitas browser. Saya pergi ke rute perbaikan manual hanya untuk kemudian menemukan ada lebih banyak masalah yang hanya akan Anda temukan di jalan. Sebenarnya tidak terlalu sulit saat ini:
Dan baca api di https://github.com/browserstate/history.js
sumber
Ini memecahkan masalah saya. Yang saya lakukan hanyalah menyetel fungsi batas waktu yang menunda pelaksanaan fungsi cukup lama untuk melewatkan acara popstate yang diaktifkan di pageload
sumber
Anda dapat membuat acara dan mengaktifkannya setelah onload handler Anda.
Catatan, ini sedikit rusak di Chrome / Safari, tetapi saya telah mengirimkan tambalan ke WebKit dan itu akan segera tersedia, tetapi ini adalah cara yang "paling benar".
sumber
Ini berfungsi untuk saya di Firefox dan Chrome
sumber