Có sự kiện tải trên trình duyệt chéo khi nhấp vào nút quay lại không?


185

Đối với tất cả các trình duyệt chính (trừ IE), onloadsự kiện JavaScript không kích hoạt khi trang tải do hoạt động của nút quay lại - nó chỉ kích hoạt khi trang được tải lần đầu tiên.

Ai đó có thể chỉ cho tôi một số mã trình duyệt chéo mẫu (Firefox, Opera, Safari, IE, xóa) để giải quyết vấn đề này không? Tôi quen thuộc với pageshowsự kiện của Firefox nhưng tiếc là cả Opera và Safari đều không thực hiện điều này.


6
Đây không phải là vấn đề - nó cho phép trang web được tải nhanh khi người dùng nhấn nút Quay lại. Xem câu trả lời của tôi dưới đây để biết chi tiết. Các cách giải quyết được đề xuất ở đây làm cho trang web gây khó chịu hơn cho người dùng, vì điều hướng lùi / tiến chậm hơn.
Nickolay

2
@romkyns: bình luận của bạn không liên quan đến câu hỏi này. Khi các trình duyệt không khôi phục trạng thái JS / DOM, chúng sẽ kích hoạt sự kiện tải.
Nickolay

Nút quay lại lịch sử iOS 5+ đã được giải quyết tại đây stackoverflow.com/a/12652160/1090395
Mladen Janjetovic

Câu trả lời:


117

Các bạn, tôi thấy rằng JQuery chỉ có một hiệu ứng: trang được tải lại khi nhấn nút quay lại. Điều này không có gì để làm với " sẵn sàng ".

Cái này hoạt động ra sao? Chà, JQuery thêm một trình nghe sự kiện onunload .

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

Theo mặc định, nó không làm gì cả. Nhưng bằng cách nào đó, điều này dường như kích hoạt tải lại trong Safari, Opera và Mozilla - bất kể trình xử lý sự kiện có chứa gì.

[ chỉnh sửa (Nickolay) : đây là lý do tại sao nó hoạt động theo cách đó: webkit.org , developer.mozilla.org . Vui lòng đọc các bài viết đó (hoặc tóm tắt của tôi trong một câu trả lời riêng bên dưới) và xem xét liệu bạn có thực sự cần phải làm điều này không và làm cho trang của bạn tải chậm hơn cho người dùng của bạn.]

Không thể tin được? Thử cái này:

<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>

Bạn sẽ thấy kết quả tương tự khi sử dụng JQuery.

Bạn có thể muốn so sánh với trang này mà không 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>

1
Rất đẹp .. mặc dù đây là một tính năng / lỗi không có giấy tờ, và có thể chỉ đơn giản là ngừng hoạt động trong các phiên bản tương lai của trình duyệt, nhưng nó vẫn thú vị.
Wadih M.

3
Điều này cũng hoạt động (đừng quên phần onunload = "", nếu không sẽ không hoạt động trên ff3): <body onload = "alert ('onload');" onunload = "">
Wadih M.

3
Điều này là do trình duyệt giả định trang không thể truy cập được nếu nó có onunloadtrình xử lý (trang đã phá hủy mọi thứ; tại sao lại lưu trữ nó?).
Casey Chu

14
Trả lời dường như không hoạt động trong các trình duyệt hiện đại - đã kiểm tra Chrome và Opera mới nhất
Andrew

10
nó không hoạt động trong iPad safari ... làm ơn, bỏ đánh dấu đây là câu trả lời
xus

74

Một số trình duyệt hiện đại (Firefox, Safari và Opera, nhưng không hỗ trợ Chrome) hỗ trợ bộ đệm "quay lại / chuyển tiếp" đặc biệt (tôi sẽ gọi nó là bfcache, một thuật ngữ được phát minh bởi Mozilla), liên quan khi người dùng điều hướng trở lại. Không giống như bộ đệm (HTTP) thông thường, nó lưu giữ trạng thái hoàn chỉnh của trang (bao gồm cả trạng thái của JS, DOM). Điều này cho phép nó tải lại trang nhanh hơn và chính xác khi người dùng rời khỏi nó.

Sự loadkiện này không được kích hoạt khi trang được tải từ bfcache này. Ví dụ: nếu bạn đã tạo giao diện người dùng của mình trong trình xử lý "tải" và sự kiện "tải" đã được kích hoạt một lần trên tải ban đầu và lần thứ hai khi trang được tải lại từ bfcache, trang sẽ kết thúc bằng các yếu tố UI trùng lặp.

Đây cũng là lý do tại sao việc thêm trình xử lý "unload" ngăn trang được lưu trữ trong bfcache (do đó làm cho nó chậm hơn để điều hướng trở lại) - trình xử lý unload có thể thực hiện các tác vụ dọn dẹp, có thể khiến trang ở trạng thái không thể hoạt động.

Đối với các trang cần biết khi chúng được điều hướng đi / quay lại, Firefox 1.5+ và phiên bản Safari với bản sửa lỗi 28758 hỗ trợ các sự kiện đặc biệt có tên là "pagehow" và "page leather".

Người giới thiệu:


Điều đó thật ngầu. Tôi đang ở trong một tình huống hiện tại nơi các thao tác dom của tôi dường như không được lưu trong bfcache. Có bất kỳ tình huống mà bạn có thể mong đợi điều đó?
Benson

1
@Benson: những lý do có thể xảy ra khi Firefox sẽ không lưu trang của bạn trong bfcache được liệt kê trên trang dev.mo mà tôi liên kết đến. Tôi không nghĩ có thể lưu trang vào bfcache, nhưng trạng thái DOM nhất định không được lưu.
Nickolay

Nickolay, tôi miễn cưỡng buộc bạn tải lại và hoàn tác tốt công việc của bfcache, nhưng có cách nào khác để cập nhật sự thống trị của trang trong bfcache không? Ví dụ, hãy xem xét tình huống tôi đi từ một trang có danh sách các tin nhắn đến một trong số chúng và khi tôi "quay lại" tôi muốn chỉ báo đọc / chưa đọc thay đổi. Làm thế nào điều này có thể được thực hiện mà không cần tải lại trang?
Greg

@Greg: ý bạn là nhà phát triển kiểm soát trang? Bắn ra một yêu cầu ajax từ người nghe 'pagehow'.
Nickolay

Bạn có ý tưởng nào về cách sử dụng jQuery VÀ nhận hỗ trợ bfcache nhanh không?
Alex Black

31

Tôi gặp phải một vấn đề mà js của tôi không thực thi khi người dùng đã nhấp trở lại hoặc chuyển tiếp. Trước tiên tôi đặt ra để ngăn trình duyệt lưu vào bộ đệm, nhưng điều này dường như không phải là vấn đề. Javascript của tôi đã được thiết lập để thực thi sau khi tất cả các thư viện, vv được tải. Tôi đã kiểm tra những thứ này với sự kiện readyStateChange.

Sau một số thử nghiệm, tôi phát hiện ra rằng readyState của một phần tử trong trang đã nhấp vào trở lại không phải là 'được tải' mà là 'hoàn thành'. Thêm || element.readyState == 'complete'vào tuyên bố điều kiện của tôi giải quyết vấn đề của tôi.

Chỉ cần nghĩ rằng tôi chia sẻ những phát hiện của tôi, hy vọng họ sẽ giúp đỡ người khác.

Chỉnh sửa cho đầy đủ

Mã của tôi trông như sau:

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

Trong mẫu mã phía trên biến tập lệnh là một phần tử tập lệnh mới được tạo đã được thêm vào DOM.


7
Bạn đã thêm cái này ở đâu? Và làm thế nào bạn có được bất cứ thứ gì để bắn sau khi người dùng quay trở lại? Vui lòng cho chúng tôi xem một số mã!
Keerigan

Ý bạn là gì khi bạn nói "tuyên bố điều kiện của tôi"?
Phillip Senn

1
@Phillip Một câu lệnh có điều kiện là một câu lệnh if.
Brian Heese

22

OK, đây là một giải pháp cuối cùng dựa trên giải pháp ban đầu của ckramer và ví dụ của palehorse hoạt động trong tất cả các trình duyệt, bao gồm cả Opera. Nếu bạn đặt history.navlationMode thành 'tương thích' thì chức năng sẵn sàng của jQuery sẽ kích hoạt các hoạt động của nút Quay lại trong Opera cũng như các trình duyệt chính khác.

Trang này có nhiều thông tin hơn .

Thí dụ:

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

Tôi đã thử nghiệm điều này trong Opera 9.5, IE7, FF3 và Safari và nó hoạt động trong tất cả chúng.


2
Rõ ràng đã được một thời gian (khoảng 5,5 năm) nhưng đáng chú ý là liên kết của bạn đã chết.
Jeff

2
Giải pháp này không hiệu quả với tôi. Tôi đã gặp sự cố này trong Firefox mới nhất (45.0.1)
Armin

6

Tôi không thể có được các ví dụ trên để làm việc. Tôi chỉ đơn giản muốn kích hoạt làm mới một số khu vực div đã sửa đổi khi quay lại trang thông qua nút quay lại. Thủ thuật tôi đã sử dụng là đặt trường đầu vào ẩn (được gọi là "bit bẩn") thành 1 ngay khi các vùng div thay đổi so với ban đầu. Trường đầu vào ẩn thực sự giữ lại giá trị của nó khi tôi nhấp lại, vì vậy khi tải tôi có thể kiểm tra bit này. Nếu được đặt, tôi làm mới trang (hoặc chỉ làm mới div). Tuy nhiên, trên tải ban đầu, bit không được đặt, vì vậy tôi không lãng phí thời gian tải trang hai lần.

<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>

Và nó sẽ kích hoạt đúng cách bất cứ khi nào tôi nhấp vào nút quay lại.


3
Mặc dù điều này không hoạt động trong Firefox, tôi nghĩ rằng đây là một cách khôn ngoan để xử lý tình huống trong IE / Chrome trong đó tính bền bỉ của trường ẩn là rất hữu ích. Tôi đã sử dụng mánh khóe của bạn và cả sự kiện "pagehow", vì vậy tôi bao quát tất cả các trình duyệt chính.
Magnus Smith

Trình duyệt nào không hoạt động với các trang mà điều này không có?
Justin

4

Nếu tôi nhớ đúng, thì việc thêm một sự kiện unload () có nghĩa là trang đó không thể được lưu vào bộ đệm (trong bộ đệm tiến / lùi) - bởi vì trạng thái của nó thay đổi / có thể thay đổi khi người dùng điều hướng đi. Vì vậy - không an toàn để khôi phục trạng thái giây cuối cùng của trang khi quay lại trang đó bằng cách điều hướng qua đối tượng lịch sử.


4

Tôi nghĩ rằng đây sẽ là "onunload", không phải tải trang, vì chúng ta không nói về việc bắn một sự kiện khi nhấn "Quay lại"? $ document. yet () dành cho các sự kiện mong muốn khi tải trang, bất kể bạn truy cập trang đó như thế nào (tức là chuyển hướng, mở trình duyệt tới URL, v.v.), không phải khi nhấp vào "Quay lại", trừ khi bạn đang nói về những gì sẽ bắn vào trang trước khi nó tải lại. Và tôi không chắc rằng trang sẽ không được lưu trong bộ nhớ cache vì tôi thấy rằng Javascripts vẫn còn, ngay cả khi $ document. Yet () được bao gồm trong chúng. Chúng tôi đã phải nhấn Ctrl + F5 khi chỉnh sửa tập lệnh có sự kiện này bất cứ khi nào chúng tôi sửa lại chúng và chúng tôi muốn kiểm tra kết quả trong các trang của mình.

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

là những gì bạn muốn cho một sự kiện onunload khi nhấn "Quay lại" và dỡ trang hiện tại và cũng sẽ kích hoạt khi người dùng đóng cửa sổ trình duyệt. Điều này nghe có vẻ giống như những gì mong muốn, ngay cả khi tôi đông hơn với các phản hồi $ document. Yet (). Về cơ bản, sự khác biệt là giữa một sự kiện đang diễn ra trên trang hiện tại trong khi nó đang đóng hoặc trên một sự kiện tải khi nhấp vào "Quay lại" khi nó đang tải. Đã thử nghiệm trong IE 7 tốt, không thể nói cho các trình duyệt khác vì chúng không được phép ở nơi chúng tôi đang ở. Nhưng đây có thể là một lựa chọn khác.


4

Tôi có thể xác nhận ckramer rằng sự kiện sẵn sàng của jQuery hoạt động trong IE và FireFox. Đây là một mẫu:

<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>

4

Đối với những người không muốn sử dụng toàn bộ thư viện jquery, tôi đã trích xuất việc thực hiện theo mã riêng. Nó chỉ lớn 0,4 KB.

Bạn có thể tìm thấy mã, cùng với một hướng dẫn tiếng Đức trong wiki này: http://www.easy-coding.de/wiki/html-ajax-und-co/onload-event-cross-browser-kompatibler-domcontentloaded.html


1
Liên kết đơn độc được coi là một câu trả lời kém (xem faq ) vì bản thân nó là vô nghĩa và tài nguyên đích không được đảm bảo để tồn tại trong tương lai . Tốt hơn là nên bao gồm các phần thiết yếu của câu trả lời ở đây và cung cấp liên kết để tham khảo.
j0k

3

Sự kiện sẵn sàng của jQuery được tạo ra chỉ cho loại vấn đề này. Bạn có thể muốn đi sâu vào việc thực hiện để xem những gì đang diễn ra dưới vỏ bọc.


6
Một thời gian dài sau, readydường như không được kích hoạt trong Firefox, khi sử dụng nút Quay lại. Xem thêm câu trả lời của Nickolay .
Arjan

2

Bill, tôi dám trả lời câu hỏi của bạn, tuy nhiên tôi không chắc chắn 100% với dự đoán của mình. Tôi nghĩ các trình duyệt IE khác khi đưa người dùng đến một trang trong lịch sử sẽ không chỉ tải trang và tài nguyên của nó từ bộ đệm mà còn khôi phục toàn bộ trạng thái DOM (phiên đọc) cho nó. IE không thực hiện khôi phục DOM (hoặc cho thuê đã không thực hiện) và do đó, sự kiện onload dường như là cần thiết để khởi tạo lại trang thích hợp ở đó.


2

Tôi đã thử giải pháp từ Bill bằng cách sử dụng $ (tài liệu). Đã ... nhưng lúc đầu, nó không hoạt động. Tôi phát hiện ra rằng nếu tập lệnh được đặt sau phần html, nó sẽ không hoạt động. Nếu nó là phần đầu, nó sẽ hoạt động nhưng chỉ trong IE. Kịch bản không hoạt động trong Firefox.


1

OK, tôi đã thử cái này và nó hoạt động trong Firefox 3, Safari 3.1.1 và IE7 nhưng không có trong Opera 9.52.
Nếu bạn sử dụng ví dụ được hiển thị bên dưới (dựa trên ví dụ của palehorse), bạn sẽ nhận được một hộp cảnh báo bật lên khi trang tải lần đầu tiên. Nhưng nếu sau đó bạn truy cập một URL khác, rồi nhấn nút Quay lại để quay lại trang này, bạn sẽ không nhận được hộp thông báo bật lên trong Opera (nhưng bạn làm trong các trình duyệt khác).

Dù sao, tôi nghĩ rằng điều này là đủ gần bây giờ. Cảm ơn mọi người!

<!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>

1

Unload event không hoạt động tốt trên IE 9. Tôi đã thử nó với load event (onload ()), nó hoạt động tốt trên IE 9FF5 .

Thí dụ:

<%@ 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>

0

Tôi đã sử dụng một mẫu html. Trong tệp custom.js của mẫu này, có một hàm như thế này:

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

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

    });

Nhưng chức năng này không hoạt động khi tôi quay lại sau khi đi đến trang khác.

Vì vậy, tôi đã thử điều này và nó đã hoạt động:

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

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

Bây giờ, tôi có 2 chức năng "sẵn sàng" nhưng nó không đưa ra bất kỳ lỗi nào và trang đang hoạt động rất tốt.

Tuy nhiên, tôi phải tuyên bố rằng nó đã thử nghiệm trên Windows 10 - Opera v53 và Edge v42 nhưng không có trình duyệt nào khác. Hãy ghi nhớ điều này ...

Lưu ý: phiên bản jquery là 3.3.1 và phiên bản di chuyển là 3.0.0

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.