Ajax, tombol kembali dan pembaruan DOM

113

Jika javascript memodifikasi DOM di halaman A, pengguna menavigasi ke halaman B dan kemudian menekan tombol kembali untuk kembali ke halaman A. Semua modifikasi pada DOM halaman A hilang dan pengguna disajikan dengan versi yang aslinya diambil dari server.

Ini berfungsi seperti itu di stackoverflow, reddit, dan banyak situs web populer lainnya. (coba tambahkan komentar percobaan ke pertanyaan ini, lalu navigasikan ke halaman lain dan tekan tombol kembali untuk kembali - komentar Anda akan "hilang")

Ini masuk akal, namun beberapa situs web (apple.com, basecamphq.com, dll) memaksa browser untuk menyajikan status halaman terbaru kepada pengguna. (buka http://www.apple.com/ca/search/?q=ipod , klik ucapkan tautan Unduhan di bagian atas lalu klik tombol kembali - semua pembaruan DOM akan dipertahankan)

darimana datangnya ketidakkonsistenan?

lubos hasko
sumber
Menariknya, Apple mengingat negara tanpa memodifikasi hash .. hmmm
James
Apple sepertinya mereka hanya memanipulasi cache respons
BigBlondeViking
Seperti yang telah disarankan orang lain ini bukan sesuatu yang berhubungan dengan javascript atau ajax. Anda harus menghapus tag tersebut untuk mendapatkan jawaban yang benar.
BYK
Contoh Apple buruk. Jika Anda mengontrak area pencarian [mis: produk], klik tautan Anda, lalu tekan kembali, DOM tidak dipertahankan. Anda mencari Solusi Hash yang banyak disarankan.
BigBlondeViking
Ketika saya menekan tombol kembali, Apple sama sekali tidak ingat halaman hasil pencarian apa yang saya buka. Menggunakan IE7. Anda membutuhkan solusi hash. Lihat: Facebook.
Josh Stodola

Jawaban:

106

Satu jawaban: Antara lain, peristiwa unload menyebabkan cache mundur / maju menjadi tidak valid .

Beberapa browser menyimpan status terkini dari keseluruhan halaman web dalam apa yang disebut "bfcache" atau "cache halaman". Ini memungkinkan mereka merender ulang halaman dengan sangat cepat saat menavigasi melalui tombol kembali dan maju, dan mempertahankan status DOM dan semua variabel JavaScript. Namun, jika halaman berisi peristiwa saat muat ulang, peristiwa tersebut berpotensi membuat halaman menjadi tidak berfungsi, sehingga halaman tidak disimpan di bfcache dan harus dimuat ulang (tetapi dapat dimuat dari cache standar) dan dirender dari awal, termasuk menjalankan semua penangan onload. Saat kembali ke halaman melalui bfcache, DOM disimpan dalam keadaan sebelumnya, tanpa perlu mengaktifkan penangan onload (karena halaman sudah dimuat).

Perhatikan bahwa perilaku bfcache berbeda dari cache browser standar dalam kaitannya dengan Cache-Control dan header HTTP lainnya. Dalam banyak kasus, browser akan menyimpan halaman di bfcache meskipun jika halaman tidak disimpan dalam cache standar.

jQuery secara otomatis melampirkan acara unload ke jendela, jadi sayangnya menggunakan jQuery akan mendiskualifikasi halaman Anda dari disimpan di bfcache untuk pelestarian DOM dan cepat mundur / maju. [Pembaruan: ini telah diperbaiki di jQuery 1.4 sehingga hanya berlaku untuk IE]

Miles
sumber
3
Anda benar-benar berhasil. keduanya, reddit dan stackoverflow menggunakan jquery sedangkan basecamp dan apple menggunakan prototypejs. ini cukup banyak menjelaskan segalanya.
lubos hasko
+1 menarik (meskipun bukan lintas browser) pertanyaannya jauh berbeda dari saat dimulai ...
BigBlondeViking
1
ini mungkin lintas-browser karena saya dapat mereproduksinya di Internet Explorer saya juga. Saya yakin setiap browser web dengan javascript diaktifkan harus menangani masalah ini. tetapi ini benar-benar berantakan, ketika Anda memikirkannya, tombol kembali harus selalu mengarahkan orang ke halaman yang terakhir mereka lihat dengan semua pembaruan DOM, status javascript, dll. pengembang tidak boleh merusak ini dengan melakukan sesuatu dalam acara pembongkaran dan jika ya, peramban web tidak boleh mencoba memperbaiki masalah dengan tidak menggunakan bfcache sama sekali. seluruh acara bongkar adalah satu lelucon besar. Saya yakin 99% waktu digunakan untuk menambal kebocoran memori.
lubos hasko
1
Secara khusus, kebocoran memori IE. :) Peristiwa unload jQuery juga terjadi untuk memperbaiki bug (yang sama sekali tidak terkait) di Firefox 2. Tapi ini tidak diperlukan untuk browser lain. dev.jquery.com/ticket/3015 Saya kira saya pernah mendengar tentang kegunaan lain untuk pembongkaran, seperti pelacakan klik keluar atau menyimpan status aplikasi web , tetapi saya tidak pernah punya alasan untuk menggunakannya sendiri, dan jika pengembang ingin membuatnya situs lebih lambat dan lebih menyakitkan bagi penggunanya (saya benci bagaimana menavigasi kembali ke halaman komentar reddit menyetel ulang status komentar diciutkan), itulah hak prerogatif mereka.
Miles
1
Acara unload hanya dilampirkan untuk IE, bukan untuk firefox dan chrome. Versi terbaru dari safari mempertahankan status dom tanpa harus melakukan apa pun.
David
15

Saya telah mencoba membuat Chrome berperilaku seperti Safari, dan satu-satunya cara yang berhasil adalah dengan mengatur Cache-control: no-storeheader. Ini memaksa browser untuk mengambil kembali halaman dari server saat pengguna menekan tombol kembali. Tidak ideal, tetapi lebih baik daripada diperlihatkan halaman yang sudah kadaluwarsa.

nornagon.dll
sumber
5
Ini adalah jawaban yang benar untuk pertanyaan awal. Jika Anda ingin memaksa server memuat ulang pada tombol kembali, gunakan kontrol-cache 'no-store, no-cache, must-revalidate'. Chrome menginginkan tidak ada penyimpanan, dan IE ingin memvalidasi ulang. Untuk browser lain (dan w3c), tidak ada cache yang cukup.
woens
3

Facebook mengingat status halaman dengan memodifikasi pengenal hash di URL untuk permintaan ajax. Perubahan ini dicatat dalam riwayat browser, jadi ketika pengguna mengklik tombol kembali, hash berubah seperti sebelumnya. Jadi tersirat bahwa Anda akan membutuhkan beberapa Javascript untuk memantau pengenal has dan bereaksi ketika diubah oleh browser. Andreas Blixt memiliki skrip pemantauan hash yang tersedia .

Josh Stodola
sumber
pada hari ini tidak ada yang melakukannya sehingga saya dapat memberi tahu saya apa yang dilakukan facebook sekarang
Ravinder Payal
3

Ini tidak ada hubungannya dengan simbol hash (#).

Jika Anda ingin memeriksa header HTTP apple, itu hanya menyimpan halaman.

Luca Matteis
sumber
Contoh Apple buruk, mereka tidak "menyimpan" status halaman, asumsinya bahwa DOM disimpan dengan salah
BigBlondeViking
2

Menggunakan pengenal hash / fragmen URL adalah cara yang cukup umum untuk menghubungkan / mengingat status dalam aplikasi web yang bergantung pada pembaruan Ajax dan DOM.

Lihat proyek Sejarah Sangat Sederhana untuk beberapa ide. Dimungkinkan untuk memonitor URL untuk perubahan pada hash, dan rsh melakukan ini, dengan mempertimbangkan perbedaan browser.

Peter
sumber
1

Untuk siapa pun yang mengalami masalah dengan Railsdan ini - masalah Anda bukanlah bfcache (saya kira dulu) - ini turbolinkspermata. Berikut cara menghapusnya.

Mudah-mudahan ini akan menghemat waktu Anda dan membenturkan kepala Anda ke dinding.

Yuval Karmi
sumber
0

Apa yang Anda cari adalah untuk beberapa jenis manajemen hash URL. # Di url hanya untuk sisi klien.

Saat Anda mengubah status kembali dengan JS, maka Anda memperbarui data di # url.

Anda juga menambahkan beberapa jenis polling yang memantau jika hash telah berubah, dan memuat status halaman berdasarkan data baru di hash.

Lihatlah ini:

http://ajaxpatterns.org/Unique_URLs

BigBlondeViking
sumber
3
ini tidak ada hubungannya dengan simbol hash.
Luca Matteis
3
Anda salah, dia mencari cara paling umum untuk mempertahankan status halaman dalam solusi AJAX.
BigBlondeViking