Sau khi quay lại lịch sử Firefox, JavaScript sẽ không chạy


84

Khi tôi sử dụng nút quay lại trên Firefox để truy cập trang đã truy cập trước đó, các tập lệnh trên trang đó sẽ không chạy lại .

bất kỳ bản sửa lỗi / giải pháp nào để các tập lệnh thực thi lại khi xem trang lần thứ hai không?

Xin lưu ý rằng tôi đã thử nghiệm các trang giống nhau trên Google Chrome và Internet Explorer và chúng hoạt động như dự kiến.


Dưới đây là các tệp và các bước tôi đã sử dụng để kiểm tra sự cố:

(điều hướng đến 0.html, nhấp để đến 1.html, nút quay lại)

0.html

<html><body>
<script>
  window.onload = function() { alert('window.onload alert'); };
  alert('inline alert');
</script>
<a href="1.html">Click Me!</a>
</body></html>

1.html

<html><body>
<p>Go BACK!</p>
</body></html>

Câu trả lời:


92

Đặt một hàm trống sẽ được gọi trên window.onunload:

window.onunload = function(){}; 

ví dụ

<html><body>
<script type="text/javascript">
  window.onload = function() { alert('window.onload alert'); };
  window.onunload = function(){};
  alert('inline alert');
</script>
<a href="1.html">Click Me!</a>
</body></html>

Nguồn: http://www.firefoxanswer.com/firefox/672-firefoxanswer.html (Phiên bản lưu trữ)


2
Cảm ơn bạn, nó hoạt động. Bất kỳ gợi ý nào về trình xử lý onunload mặc định làm gì? (ví dụ: tôi có đang ghi đè một hành vi mặc định nào đó ở đây không?)
Patonza

Ok, cảm ơn, tôi sẽ điều tra. Cảm ơn bạn một lần nữa, vấn đề này đã ám ảnh tôi một thời gian :)
Patonza

có ai biết tại sao FireFox cần điều này trong khi các trình duyệt khác thì không?
Pim Jager

7
Bạn không ghi đè bất cứ thứ gì, điều này chỉ ngăn Firefox lưu vào bộ nhớ đệm của trang trong Back-Forward Cache (bfcache). developer.mozilla.org/en/DOM/window.onunload developer.mozilla.org/En/Using_Firefox_1.5_caching
Chris Haas

1
Mặc dù nó sẽ phá vỡ bfcache, rất tiếc, có vẻ như nó vẫn nhớ trang trước đó - cụ thể là các url iframe đã được tải sẽ được tải lại khi bạn quay lại và nếu nội dung đã tạo cần được đặt trong khung, có vẻ như không có trình duyệt chéo cách để làm mới lại.
NoBugs

76

Khi tôi sử dụng nút quay lại trên Firefox để truy cập trang đã truy cập trước đó, các tập lệnh trên trang đó sẽ không chạy lại.

Điều đó đúng và đó là một điều tốt.

Khi bạn nhấn vào một liên kết trong Firefox (và Safari và Opera), nó không phá hủy ngay trang của bạn để chuyển sang trang tiếp theo. Nó giữ cho trang nguyên vẹn, chỉ ẩn nó khỏi chế độ xem. Nếu bạn nhấn nút quay lại, nó sẽ đưa trang cũ trở lại xem mà không cần phải tải lại tài liệu; điều này nhanh hơn nhiều, dẫn đến chuyển tiếp trang trở lại / chuyển tiếp mượt mà hơn cho người dùng.

Tính năng này được gọi là bfcache .

Mọi nội dung bạn đã thêm vào trang trong quá trình tải trước đó của người dùng và sử dụng nội dung đó sẽ vẫn ở đó. Mọi trình xử lý sự kiện bạn đã đính kèm vào các phần tử trang sẽ vẫn được đính kèm. Mọi khoảng thời gian chờ / khoảng thời gian bạn đặt sẽ vẫn hoạt động. Vì vậy, hiếm khi có bất kỳ lý do gì bạn cần biết rằng bạn đã bị ẩn và hiển thị lại. Sẽ là sai khi gọi lại onloadhoặc nội dòng mã script, bởi vì bất kỳ liên kết và tạo nội dung nào mà bạn đã thực hiện trong hàm đó sẽ được thực thi lần thứ hai trên cùng một nội dung, với kết quả có thể thảm hại. (ví dụ: document.writetrong tập lệnh nội tuyến sẽ phá hủy hoàn toàn trang.)

Lý do viết thư window.onunloadcó tác dụng là do các trình duyệt triển khai bfcache đã quyết định rằng - để tương thích với các trang thực sự cần biết khi nào chúng bị loại bỏ - bất kỳ trang nào tuyên bố quan tâm đến việc biết khi nào onunloadxảy ra sẽ khiến bfcache bị vô hiệu hóa. Trang đó sẽ được tải mới khi bạn quay lại, thay vì được tải từ bfcache.

Vì vậy, nếu bạn thiết lập window.onunload= function() {};, những gì bạn thực sự đang làm là cố tình phá vỡ bfcache. Điều này sẽ dẫn đến việc các trang của bạn điều hướng chậm và không nên được sử dụng trừ khi là phương sách cuối cùng.

Nếu bạn cần biết khi nào người dùng rời đi hoặc quay lại trang của bạn, mà không làm rối bfcache, bạn có thể bẫy các sự kiện onpageshowonpagehidethay thế:

window.onload=window.onpageshow= function() {
    alert('Hello!');
};

3
Vấn đề của tôi là bfcache không cache TẤT CẢ trang nên tôi phải chạy lại js để xây dựng lại nội dung bị mất. Vì vậy, đập toàn bộ trang có thể được. Dù sao, tôi không sử dụng sự kiện window.onload, tôi đang sử dụng sự kiện jQuery document.ready. Bạn có biết cách nào để vẫn có thể sử dụng document.ready và tránh được vấn đề này không?
Patonza

bfcache nói chung sẽ trả lại toàn bộ trang như khi nó được để lại. Nội dung bị thiếu sau khi quay lại từ trang trước là gì? (trường hợp thử nghiệm?) document.readyvề cơ bản sẽ hoạt động theo cùng một cách như window.onload(đối với một số trình duyệt, chúng vẫn là cùng một sự kiện).
bobince

14
Đó KHÔNG phải là điều tốt vì nó không chạy lại javascript, coi như nó đã được lưu trong bộ nhớ cache ... nhưng KHÔNG thực sự lưu vào bộ nhớ cache những thay đổi mà javascript đã thực hiện trước đó. Nếu javascript mờ dần trong một phần tử khi tải trang, nó sẽ không làm mờ nó một lần nữa khi truy cập trong lịch sử ... nhưng KHÔNG bắt đầu lại nó ở 0 opacity, hoàn tác những gì javascript đã làm! Nó phải là TẤT CẢ HOẶC KHÔNG GÌ. Bạn phải lưu trạng thái hoàn chỉnh của trang vào bộ đệm sau khi javascript đã chạy nếu bạn muốn trình bày nó đã được lưu vào bộ đệm mà không chạy lại javascript!
Jimbo Jonny

1
@Jimbo: Làm ơn test case. bfcache nhằm mục đích (và trong mọi trường hợp tôi từng thấy, đều làm như vậy) bảo toàn trạng thái chính xác của DOM qua ẩn / hiện. Một phần tử đã bị mờ đi sẽ vẫn mờ khi trang được quay lại, trừ khi một số tập lệnh khác chạy để ẩn nó một lần nữa.
bobince

1
@bobince - Tạo một phần tử bằng tệp CSS đặt độ mờ bằng 0 và sau đó sử dụng một số jQuery để làm cho nó mờ dần trên tài liệu đã sẵn sàng. Khi quay lại lịch sử, nó sẽ áp dụng lại CSS của biểu định kiểu (số 0) mà không giữ độ mờ: 1 mà JS đã thêm vào thuộc tính style khi làm mờ nó. Lần đầu tiên bạn truy cập trang, phần tử sẽ mờ dần từ 0 xuống 1. Đi đến một trang khác và nhấn lại và nó sẽ hoàn toàn trong suốt ở đó.
Jimbo Jonny

23

Bạn có thể kiểm tra thuộc persistedtính của pageshowsự kiện. Nó được đặt thành false khi tải trang đầu tiên. Khi trang được tải từ bộ nhớ cache, nó được đặt thành true.

window.onpageshow = function(event) {
    if (event.persisted) {
        alert("From bfcache");
    }
};

Vì một số lý do jQuery không có thuộc tính này trong sự kiện. Bạn có thể tìm thấy nó từ sự kiện ban đầu.

$(window).bind("pageshow", function(event) {
    if (event.originalEvent.persisted) {
        alert("From bfcache");
    }
});

Cảm ơn bạn đã cung cấp cả phiên bản javascript và jquery! Bạn đã bỏ lỡ dấu ngoặc nhọn ở cuối ở đó (đây không phải là tiếng rên rỉ!). Tôi cũng sẽ lưu ý, vì lợi ích của những người khác, báo cáo IE và Chrome .persisted luôn là sai, bất kể.
Magnus Smith

Theo lưu ý của Magnus, điều này không hoạt động với tôi trong Chrome cho đến khi tôi xóa câu lệnh if.
Justin

Điều này hoạt động với tôi trong Chrome 58.0.3029.110 (64-bit) và FF 53.0.2 (64-bit) mà không có bất kỳ thay đổi nào.
kmoser

1

Wire trong sự kiện "onunload" mà không làm gì:

<html><body>
<script type="text/javascript">
  window.onload = function() { alert('window.onload alert'); };
  window.onunload = function(){}; 
  alert('inline alert');
</script>
<a href="1.html">Click Me!</a>
</body></html>

Bạn không chắc chắn, tôi đã đưa ra một Answer, trông giống như ai đó chỉ downvoted mỗi câu trả lời cho câu hỏi này ...
Patonza

bạn nên thêm vào câu trả lời của mình rằng việc thêm sự kiện onunload vào trang của bạn sẽ thực sự vô hiệu hóa toàn bộ trang đang được lưu trong bộ nhớ cache. Điều này không chỉ đơn giản là làm cho JS chạy lại mà còn làm cho tải của máy chủ tăng lên một bậc. Đây thực sự không phải là một gợi ý xem nhẹ, điều này cần được xem xét cẩn thận.
dreagan

@dreagan, điều này vô hiệu hóa bfcache nhưng không nhất thiết phải là HTTP cache. Bộ đệm HTTP có một bộ quy tắc hoàn toàn khác. Nếu bạn đặt chế độ ngủ phía máy chủ ở đó, bạn sẽ thấy nó trong khi nhấp lại. Mozilla nói về điều này trong câu hỏi thứ ba của họ trên Câu hỏi thường gặp về BFCache .
Chris Haas

Tôi đã nói về BFcache, lẽ ra phải chỉ rõ điều đó. Điều đó không có nghĩa là bạn nên đưa ra một đề xuất như thế này mà không thông báo cho OP về hậu quả. Một giải pháp thay thế sẽ là sử dụng sự kiện onpopstate để thử và kích hoạt lại javascript.
dreagan

Tôi vẫn không biết nếu tôi hiểu. Tại sao "tải của máy chủ sẽ tăng lên một bậc" nếu bfcache cục bộ của máy khách bị bỏ qua? Có, DOM sẽ cần được xây dựng lại, nhưng HTML phải là một phần của bộ đệm HTTP của máy khách. Có, các tài nguyên bổ sung sẽ cần được tải lại, nhưng những tài nguyên đó cũng phải là một phần của bộ đệm HTTP của máy khách. Đối với onpopstate, khi câu hỏi này đã được hỏi gần năm năm trước sự kiện đó vẫn còn tương đối mới và hỗ trợ trình duyệt đã rất không phù hợp
Chris Haas

1

Theo như tôi biết Firefox không kích hoạt onLoadsự kiện trở lại.

Nó sẽ kích hoạt onFocus thay vì dựa trên liên kết này ở đây .


Đã kiểm tra nó và windows.onfocus thực sự KHÔNG được gọi, ngay cả khi không đặt trình xử lý window.onunload trống. Đặt onunload là một cách giải quyết tốt hơn một chút nhưng .onfocus cũng sẽ ổn. Cảm ơn :)
Patonza

1

Một cách đơn giản để khiến một trang thực thi JavaScript khi người dùng điều hướng trở lại trang đó bằng lịch sử trình duyệt là sự kiện OnPopState. Chúng tôi sử dụng quyền này để tạm dừng và phát lại video trên trang chủ của chúng tôi ( https://fynydd.com ).

window.onpopstate = function() {

    // Do stuff here...
};

0

đối với một số trường hợp như thao tác ajax, trình nghe thay đổi url có thể được sử dụng

$(window).on('hashchange', function() {
        ....
});
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.