(Lưu ý: Theo phản hồi của Sharky, tôi đã bao gồm mã để phát hiện các khoảng trống)
Vì vậy, tôi đã thấy những câu hỏi này thường xuyên trên SO và gần đây đã gặp phải vấn đề kiểm soát chức năng nút quay lại. Sau vài ngày tìm kiếm giải pháp tốt nhất cho ứng dụng của tôi (Trang đơn với Điều hướng Hash), tôi đã tìm ra một hệ thống đơn giản, không có trình duyệt, không có thư viện để phát hiện nút quay lại.
Hầu hết mọi người khuyên bạn nên sử dụng:
window.onhashchange = function() {
//blah blah blah
}
Tuy nhiên, chức năng này cũng sẽ được gọi khi người dùng sử dụng phần tử trong trang thay đổi vị trí băm. Không phải trải nghiệm người dùng tốt nhất khi người dùng của bạn nhấp và trang quay ngược hoặc xuôi.
Để cung cấp cho bạn một phác thảo chung về hệ thống của tôi, tôi đang lấp đầy một mảng với các giá trị băm trước đó khi người dùng của tôi di chuyển qua giao diện. Nó trông giống như thế này:
function updateHistory(curr) {
window.location.lasthash.push(window.location.hash);
window.location.hash = curr;
}
Khá thẳng về phía trước. Tôi làm điều này để đảm bảo hỗ trợ nhiều trình duyệt, cũng như hỗ trợ cho các trình duyệt cũ hơn. Chỉ cần chuyển hàm băm mới cho hàm và nó sẽ lưu nó cho bạn và sau đó thay đổi hàm băm (sau đó được đưa vào lịch sử của trình duyệt).
Tôi cũng sử dụng nút quay lại trong trang để di chuyển người dùng giữa các trang bằng cách sử dụng lasthash
mảng. Nó trông như thế này:
function goBack() {
window.location.hash = window.location.lasthash[window.location.lasthash.length-1];
//blah blah blah
window.location.lasthash.pop();
}
Vì vậy, điều này sẽ di chuyển người dùng trở lại băm cuối cùng và loại bỏ băm cuối cùng đó khỏi mảng (tôi không có nút chuyển tiếp ngay bây giờ).
Vì thế. Làm cách nào để phát hiện xem người dùng đã sử dụng nút quay lại trong trang của tôi hay nút trình duyệt?
Lúc đầu tôi nhìn window.onbeforeunload
, nhưng vô ích - điều đó chỉ được gọi nếu người dùng sẽ thay đổi trang. Điều này không xảy ra trong một ứng dụng một trang sử dụng điều hướng băm.
Vì vậy, sau khi đào thêm, tôi thấy các khuyến nghị cho việc cố gắng đặt biến cờ. Vấn đề với trường hợp này là tôi sẽ cố gắng đặt nó, nhưng vì mọi thứ không đồng bộ, nên nó sẽ không luôn được đặt đúng lúc cho câu lệnh if trong thay đổi băm. .onMouseDown
không phải lúc nào cũng được gọi trong nhấp chuột và thêm nó vào một onclick sẽ không bao giờ kích hoạt nó đủ nhanh.
Đây là khi tôi bắt đầu xem xét sự khác biệt giữa document
, và window
. Giải pháp cuối cùng của tôi là đặt cờ bằng cách sử dụng document.onmouseover
và vô hiệu hóa nó bằng cách sử dụng document.onmouseleave
.
Điều xảy ra là trong khi chuột của người dùng ở trong vùng tài liệu (đọc: trang được hiển thị, nhưng không bao gồm khung trình duyệt), boolean của tôi được đặt thành true
. Ngay khi con chuột rời khỏi khu vực tài liệu, boolean lật tới false
.
Bằng cách này, tôi có thể thay đổi window.onhashchange
thành:
window.onhashchange = function() {
if (window.innerDocClick) {
window.innerDocClick = false;
} else {
if (window.location.hash != '#undefined') {
goBack();
} else {
history.pushState("", document.title, window.location.pathname);
location.reload();
}
}
}
Bạn sẽ lưu ý kiểm tra cho #undefined
. Điều này là bởi vì nếu không có lịch sử có sẵn trong mảng của tôi, nó sẽ trả về undefined
. Tôi sử dụng điều này để hỏi người dùng nếu họ muốn rời khỏi bằng cách sử dụng một window.onbeforeunload
sự kiện.
Vì vậy, trong ngắn hạn và cho những người không nhất thiết phải sử dụng nút quay lại trong trang hoặc một mảng để lưu trữ lịch sử:
document.onmouseover = function() {
//User's mouse is inside the page.
window.innerDocClick = true;
}
document.onmouseleave = function() {
//User's mouse has left the page.
window.innerDocClick = false;
}
window.onhashchange = function() {
if (window.innerDocClick) {
//Your own in-page mechanism triggered the hash change
} else {
//Browser back button was clicked
}
}
Và bạn có nó rồi đấy! một cách đơn giản, gồm ba phần để phát hiện việc sử dụng nút quay lại so với các yếu tố trong trang liên quan đến điều hướng băm.
BIÊN TẬP:
Để đảm bảo rằng người dùng không sử dụng backspace để kích hoạt sự kiện trở lại, bạn cũng có thể bao gồm các phần sau (Cảm ơn @thetoolman về Câu hỏi này ):
$(function(){
/*
* this swallows backspace keys on any non-input element.
* stops backspace -> back
*/
var rx = /INPUT|SELECT|TEXTAREA/i;
$(document).bind("keydown keypress", function(e){
if( e.which == 8 ){ // 8 == backspace
if(!rx.test(e.target.tagName) || e.target.disabled || e.target.readOnly ){
e.preventDefault();
}
}
});
});