Apakah ada acara overload lintas-browser saat mengklik tombol kembali?

185

Untuk semua browser utama (kecuali IE), onloadacara JavaScript tidak menyala ketika halaman dimuat sebagai hasil dari operasi tombol kembali - itu hanya menyala ketika halaman pertama kali dimuat.

Dapatkah seseorang mengarahkan saya ke beberapa contoh kode lintas-browser (Firefox, Opera, Safari, IE, ...) yang memecahkan masalah ini? Saya kenal dengan pageshowacara Firefox tetapi sayangnya Opera atau Safari tidak mengimplementasikan ini.

Tagihan
sumber
6
Ini bukan masalah - ini memungkinkan halaman web dimuat dengan cepat ketika pengguna menekan tombol Kembali. Lihat jawaban saya di bawah untuk detailnya. Solusi yang disarankan di sini membuat halaman web lebih mengganggu bagi pengguna, karena menavigasi kembali / maju lebih lambat.
Nickolay
2
@romkyns: komentar Anda tidak terkait dengan pertanyaan ini. Ketika browser tidak mengembalikan keadaan JS / DOM, mereka memang memecat acara memuat.
Nickolay
Tombol kembali sejarah iOS 5+ diselesaikan di sini stackoverflow.com/a/12652160/1090395
Mladen Janjetovic

Jawaban:

117

Guys, saya menemukan bahwa JQuery hanya memiliki satu efek: halaman dimuat ulang ketika tombol kembali ditekan. Ini tidak ada hubungannya dengan " siap ".

Bagaimana cara kerjanya? Yah, JQuery menambahkan pendengar acara onunload .

// http://code.jquery.com/jquery-latest.js
jQuery(window).bind("unload", function() { // ...

Secara default, itu tidak melakukan apa-apa. Tapi entah bagaimana ini tampaknya memicu pemuatan ulang di Safari, Opera dan Mozilla - tidak peduli apa yang ada di event handler.

[ sunting (Nickolay) : inilah mengapa ia bekerja seperti itu: webkit.org , developer.mozilla.org . Silakan baca artikel-artikel itu (atau ringkasan saya dalam jawaban terpisah di bawah) dan pertimbangkan apakah Anda benar - benar perlu melakukan ini dan membuat halaman Anda memuat lebih lambat untuk pengguna Anda.]

Tidak bisa percaya? Coba ini:

<body onunload=""><!-- This does the trick -->
<script type="text/javascript">
    alert('first load / reload');
    window.onload = function(){alert('onload')};
</script>
<a href="http://stackoverflow.com">click me, then press the back button</a>
</body>

Anda akan melihat hasil yang serupa saat menggunakan JQuery.

Anda mungkin ingin membandingkan yang satu ini tanpa onunload

<body><!-- Will not reload on back button -->
<script type="text/javascript">
    alert('first load / reload');
    window.onload = function(){alert('onload')};
</script>
<a href="http://stackoverflow.com">click me, then press the back button</a>
</body>
pengguna123444555621
sumber
1
Sangat bagus .. meskipun ini adalah fitur / bug yang tidak berdokumen, dan mungkin berhenti bekerja di versi browser yang akan datang, tetapi masih menarik.
Wadih M.
3
Ini juga berfungsi (jangan lupa bagian onunload = "", jika tidak tidak akan bekerja pada ff3): <body onload = "alert ('onload');" onunload = "">
Wadih M.
3
Ini karena browser menganggap halaman tersebut tidak dapat di-cache jika memiliki onunloadhandler (halaman telah menghancurkan segalanya; mengapa menyimpannya?).
Casey Chu
14
Jawabannya tampaknya tidak berfungsi di browser modern - diperiksa di Chrome dan Opera terbaru
Andrew
10
itu tidak berfungsi di iPad safari ... tolong, hapus centang pada ini sebagai jawaban
xus
74

Beberapa browser modern (Firefox, Safari, dan Opera, tetapi bukan Chrome) mendukung cache "back / forward" khusus (saya akan menyebutnya bfcache, yang merupakan istilah yang diciptakan oleh Mozilla), yang terlibat ketika pengguna menavigasi Kembali. Tidak seperti cache (HTTP) biasa, cache menangkap kondisi lengkap halaman (termasuk status JS, DOM). Ini memungkinkannya memuat ulang halaman lebih cepat dan persis seperti yang ditinggalkan pengguna.

The loadevent tidak seharusnya api ketika halaman dibuka dari bfcache ini. Misalnya, jika Anda membuat UI di penangan "load", dan acara "load" dipecat satu kali pada beban awal, dan kedua kalinya ketika halaman dimuat kembali dari bfcache, halaman tersebut akan berakhir dengan duplikat elemen UI.

Ini juga mengapa menambahkan handler "unload" menghentikan halaman agar tidak disimpan dalam bfcache (sehingga membuatnya lebih lambat untuk menavigasi kembali ke) - handler unload dapat melakukan tugas pembersihan, yang dapat membuat halaman dalam keadaan tidak bisa dikerjakan.

Untuk halaman yang perlu tahu kapan mereka sedang bernavigasi / kembali ke, Firefox 1.5+ dan versi Safari dengan perbaikan untuk bug 28758 mendukung acara khusus yang disebut "pageshow" dan "pagehide".

Referensi:

Nickolay
sumber
Itu sangat keren. Saya dalam situasi saat ini di mana manipulasi dom saya tampaknya tidak disimpan dalam bfcache. Apakah ada situasi di mana Anda mungkin mengharapkan itu?
Benson
1
@Benson: kemungkinan alasan ketika Firefox tidak akan menyimpan halaman Anda di bfcache tercantum di halaman dev.mo yang saya tautkan. Saya tidak berpikir mungkin untuk menyimpan halaman ke bfcache, tetapi kondisi DOM tertentu tidak disimpan.
Nickolay
Nickolay, saya mendapatkan keengganan Anda untuk memaksa memuat ulang dan membatalkan pekerjaan baik yang dilakukan oleh bfcache, tetapi apakah ada cara lain memperbarui dom halaman di bfcache? Misalnya, perhatikan situasi di mana saya pergi dari halaman yang memiliki daftar pesan ke salah satunya, dan ketika saya kembali "saya ingin indikator baca / belum dibaca berubah. Bagaimana ini bisa dilakukan tanpa memuat ulang halaman?
Greg
@Reg: maksud Anda sebagai pengembang yang mengendalikan halaman? Jalankan permintaan ajax dari pendengar 'pageshow'.
Nickolay
Ada ide tentang cara menggunakan jQuery DAN mendapatkan dukungan bfcache cepat?
Alex Black
31

Saya mengalami masalah yang tidak dieksekusi oleh js saya ketika pengguna mengklik kembali atau maju. Saya pertama kali memutuskan untuk menghentikan peramban dari caching, tetapi ini tampaknya tidak menjadi masalah. Javascript saya diatur untuk dijalankan setelah semua perpustakaan dll dimuat. Saya memeriksa ini dengan acara readyStateChange.

Setelah beberapa pengujian saya menemukan bahwa readyState elemen di halaman di mana kembali telah diklik tidak 'dimuat' tetapi 'lengkap'. Menambahkan || element.readyState == 'complete'ke pernyataan kondisional saya memecahkan masalah saya.

Hanya berpikir saya akan membagikan temuan saya, semoga mereka akan membantu orang lain.

Edit untuk kelengkapan

Kode saya terlihat sebagai berikut:

script.onreadystatechange(function(){ 
   if(script.readyState == 'loaded' || script.readyState == 'complete') {
      // call code to execute here.
   } 
});

Dalam contoh kode di atas, variabel skrip adalah elemen skrip yang baru dibuat yang telah ditambahkan ke DOM.

Brian Heese
sumber
7
Di mana Anda menambahkan ini? Dan bagaimana Anda mendapatkan sesuatu untuk ditembakkan setelah pengguna membalas? Tolong tunjukkan pada kami beberapa kode!
Keerigan
Apa maksud Anda ketika Anda mengatakan "pernyataan kondisional saya"?
Phillip Senn
1
@Phillip Pernyataan bersyarat adalah pernyataan if.
Brian Heese
22

OK, berikut ini adalah solusi final berdasarkan solusi awal ckramer dan contoh palehorse yang bekerja di semua browser, termasuk Opera. Jika Anda mengatur history.navigationMode ke 'kompatibel' maka fungsi siap jQuery akan diaktifkan pada operasi tombol Kembali di Opera serta browser utama lainnya.

Halaman ini memiliki informasi lebih lanjut .

Contoh:

history.navigationMode = 'compatible';
$(document).ready(function(){
  alert('test');
});

Saya mengujinya di Opera 9.5, IE7, FF3 dan Safari dan berfungsi di semuanya.

Tagihan
sumber
2
Jelas sudah cukup lama (sekitar 5,5 tahun) tetapi perlu dicatat bahwa tautan Anda sudah mati.
Jeff
2
Solusi ini tidak berfungsi untuk saya. Saya mengalami masalah ini di Firefox terbaru (45.0.1)
Armin
6

Saya tidak bisa membuat contoh di atas berfungsi. Saya hanya ingin memicu penyegaran area div tertentu yang dimodifikasi ketika kembali ke halaman melalui tombol kembali. Trik yang saya gunakan adalah mengatur bidang input tersembunyi (disebut "bit kotor") menjadi 1 segera setelah area div berubah dari aslinya. Bidang input tersembunyi sebenarnya mempertahankan nilainya ketika saya mengklik kembali, jadi onload saya dapat memeriksa bit ini. Jika sudah diatur, saya me-refresh halaman (atau hanya menyegarkan divs). Namun, pada pemuatan asli, bitnya tidak diatur, jadi saya tidak membuang waktu memuat halaman dua kali.

<input type='hidden' id='dirty'>

<script>
$(document).ready(function() {
  if ($('#dirty').val()) {
    // ... reload the page or specific divs only
  }
  // when something modifies a div that needs to be refreshed, set dirty=1
  $('#dirty').val('1');
});
</script>

Dan itu akan terpicu dengan benar setiap kali saya mengklik tombol kembali.

kalori
sumber
3
Meskipun ini tidak berfungsi di Firefox, saya pikir ini adalah cara yang licik untuk menangani situasi di IE / Chrome di mana kegigihan bidang tersembunyi sangat berguna. Saya telah menggunakan trik Anda dan juga acara "pageshow", jadi saya membahas semua browser utama.
Magnus Smith
Peramban apa yang tidak berfungsi dengan pageshow yang berfungsi?
Justin
4

Jika saya ingat dengan benar, maka menambahkan peristiwa unload () berarti bahwa halaman tidak dapat di-cache (dalam cache maju / mundur) - karena itu keadaan berubah / dapat berubah ketika pengguna menavigasi pergi. Jadi - tidak aman untuk mengembalikan keadaan detik terakhir dari halaman ketika kembali ke sana dengan menavigasi melalui objek sejarah.


sumber
4

Saya pikir ini untuk "onunload", bukan memuat halaman, karena bukankah kita berbicara tentang memecat suatu peristiwa ketika menekan "Kembali"? $ document.ready () adalah untuk acara yang diinginkan pada pemuatan halaman, tidak peduli bagaimana Anda sampai ke halaman itu (yaitu mengarahkan, membuka browser ke URL secara langsung, dll.), bukan ketika mengklik "Kembali", kecuali jika Anda berbicara tentang apa yang harus diaktifkan pada halaman sebelumnya ketika memuat lagi. Dan saya tidak yakin halaman tidak di-cache karena saya menemukan bahwa Javascripts masih, bahkan ketika $ document.ready () termasuk di dalamnya. Kami harus menekan Ctrl + F5 ketika mengedit skrip kami yang memiliki acara ini setiap kali kami merevisinya dan kami ingin menguji hasilnya di halaman kami.

$(window).unload(function(){ alert('do unload stuff here'); }); 

adalah apa yang Anda inginkan untuk acara onunload ketika menekan "Kembali" dan membongkar halaman saat ini, dan juga akan diaktifkan ketika pengguna menutup jendela browser. Ini terdengar lebih seperti apa yang diinginkan, bahkan jika saya kalah jumlah dengan $ document.ready (). Pada dasarnya perbedaannya adalah antara peristiwa yang terjadi pada halaman saat ini ketika sedang ditutup atau pada acara yang memuat ketika mengklik "Kembali" saat memuat. Diuji dalam IE 7 baik-baik saja, tidak dapat berbicara untuk browser lain karena mereka tidak diizinkan di mana kita berada. Tapi ini mungkin pilihan lain.

Tom
sumber
4

Saya dapat mengkonfirmasi ckramer bahwa acara siap jQuery berfungsi di IE dan FireFox. Berikut ini contohnya:

<html>
<head>
    <title>Test Page</title>
    <script src="http://code.jquery.com/jquery-latest.js" type="text/javascript"></script>
    <script type="text/javascript">
            $(document).ready(function () {
               var d = new Date();
               $('#test').html( "Hi at " + d.toString() );
            });
    </script>
</head>
<body>
    <div id="test"></div>
    <div>
        <a href="http://www.google.com">Go!</a>
    </div>
</body>
</html>
kuda pucat
sumber
4

untuk orang-orang yang tidak ingin menggunakan seluruh pustaka jquery saya mengekstrak implementasinya dalam kode terpisah. Besarnya hanya 0,4 KB.

Anda dapat menemukan kode, bersama-sama dengan tutorial bahasa Jerman di wiki ini: http://www.easy-coding.de/wiki/html-ajax-und-co/onload-event-cross-browser-kompatibler-domcontentloaded.html

Torben Brodt
sumber
1
Lone link dianggap sebagai jawaban yang buruk (lihat faq ) karena tidak ada artinya dengan sendirinya dan sumber daya target tidak dijamin akan hidup di masa depan . Akan lebih baik untuk memasukkan bagian-bagian penting dari jawaban di sini, dan menyediakan tautan untuk referensi.
j0k
3

Acara siap jQuery dibuat hanya untuk masalah seperti ini. Anda mungkin ingin menggali implementasi untuk melihat apa yang terjadi di bawah selimut.

ckramer
sumber
6
Lama kemudian, readysepertinya tidak terpicu di Firefox, saat menggunakan tombol Back. Lihat juga jawaban Nickolay .
Arjan
2

Bill, saya berani menjawab pertanyaan Anda, namun saya tidak 100% yakin dengan dugaan saya. Saya pikir selain browser IE saat membawa pengguna ke halaman dalam sejarah tidak hanya akan memuat halaman dan sumber dayanya dari cache tetapi mereka juga akan mengembalikan seluruh DOM (sesi baca) untuk itu. IE tidak melakukan restorasi DOM (atau tidak melakukan sewa) dan dengan demikian acara onload tampaknya diperlukan untuk inisialisasi ulang halaman yang benar di sana.

Sergey Ilinsky
sumber
2

Saya mencoba solusi dari Bill menggunakan $ (dokumen). Sudah ... tetapi pada awalnya itu tidak berhasil. Saya menemukan bahwa jika skrip ditempatkan setelah bagian html, itu tidak akan berfungsi. Jika itu adalah bagian kepala itu akan berfungsi tetapi hanya di IE. Skrip tidak berfungsi di Firefox.

Johann
sumber
1

OK, saya mencoba ini dan berfungsi di Firefox 3, Safari 3.1.1, dan IE7 tetapi tidak di Opera 9.52.
Jika Anda menggunakan contoh yang ditunjukkan di bawah ini (berdasarkan contoh palehorse), Anda mendapatkan kotak peringatan yang muncul saat halaman pertama kali dimuat. Tetapi jika Anda kemudian pergi ke URL lain, dan kemudian tekan tombol Kembali untuk kembali ke halaman ini, Anda tidak mendapatkan kotak peringatan yang muncul di Opera (tetapi Anda melakukannya di browser lain).

Bagaimanapun, saya pikir ini cukup dekat untuk saat ini. Terimakasih semuanya!

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Untitled Document</title>
<meta http-equiv="expires" content="0">
<script src="jquery.js" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready( 
                    function(){
                      alert('test');
                    }
                 );
</script>
</head>
<body>
<h1>Test of the page load event and the Back button using jQuery</h1>
</body>
</html>
Tagihan
sumber
1

Bongkar acara tidak berfungsi dengan baik pada IE 9. Saya mencobanya dengan memuat acara (onload ()), ia bekerja dengan baik pada IE 9 dan FF5 .

Contoh:

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript">
    jQuery(window).bind("load", function() {
        $("[name=customerName]").val('');
    });
</script>
</head>
<body>
    <h1>body.jsp</h1>
    <form action="success.jsp">
        <div id="myDiv">

        Your Full Name: <input name="yourName" id="fullName"
            value="Your Full Name" /><br> <br> <input type="submit"><br>

        </div>

    </form>
</body>
</html>
mallesham
sumber
0

Saya telah menggunakan templat html. Dalam file custom.js template ini, ada fungsi seperti ini:

    jQuery(document).ready(function($) {

       $(window).on('load', function() {
          //...
       });

    });

Tetapi fungsi ini tidak berfungsi ketika saya kembali setelah pergi ke halaman lain.

Jadi, saya mencoba ini dan berhasil:

    jQuery(document).ready(function($) {
       //...
    });

   //Window Load Start
   window.addEventListener('load', function() {
       jQuery(document).ready(function($) {
          //...
       });
   });

Sekarang, saya memiliki 2 fungsi "siap" tetapi tidak memberikan kesalahan dan halaman berfungsi dengan baik.

Namun demikian, saya harus menyatakan bahwa itu telah diuji pada Windows 10 - Opera v53 dan Edge v42 tetapi tidak ada browser lain. Ingatlah ini ...

Catatan: versi jquery adalah 3.3.1 dan versi migrasi adalah 3.0.0

bafsar
sumber