Cách kiểm tra xem người dùng có thể quay lại lịch sử trình duyệt hay không


Câu trả lời:


119

Câu trả lời ngắn gọn: Bạn không thể.

Về mặt kỹ thuật có một cách chính xác, đó là kiểm tra tài sản:

history.previous

Tuy nhiên, nó sẽ không hoạt động. Vấn đề với điều này là trong hầu hết các trình duyệt, điều này được coi là vi phạm bảo mật và thường chỉ trả về không xác định .

history.length

Là một tài sản mà người khác đã đề xuất ...
Tuy nhiên , độ dài không hoạt động hoàn toàn vì nó không cho biết bạn đang ở đâu trong lịch sử. Ngoài ra, nó không luôn luôn bắt đầu ở cùng một số. Ví dụ, một trình duyệt không được đặt để có trang đích, bắt đầu từ 0 trong khi một trình duyệt khác sử dụng trang đích sẽ bắt đầu từ 1.

văn bản thay thế

Hầu hết thời gian một liên kết được thêm vào mà gọi:

history.back();

hoặc là

 history.go(-1);

và nó chỉ mong rằng nếu bạn không thể quay lại thì nhấp vào liên kết sẽ không có gì.


Đây là thông tin tốt, nhưng nó không giải quyết được vấn đề. Nó sẽ được xây dựng một số mã thực sự hoạt động trên bất kỳ trình duyệt nào. Có lẽ một mã đầu tiên kiểm tra trình duyệt bạn đang sử dụng.
Santiago Bendavid

5
Điều tôi đang nói là không có câu trả lời dứt khoát. Bạn đang nói những ưu và nhược điểm của từng cách tiếp cận nhưng không phải là làm thế nào để có được một tập lệnh kiểm tra trình duyệt nào bạn đang sử dụng và thực thi một cách có điều kiện một hoặc các đoạn mã khác.
Santiago Bendavid

Tôi có thể hiểu ý của bạn là gì không tại sao vậy. Bất cứ ai cũng có thể đưa ra một số ví dụ về các mối đe dọa an ninh là gì?
Kevin Chandra

Một trang web không thể biết lịch sử của người dùng có thể bao gồm thông tin cá nhân gián tiếp. Một trang web có thể sử dụng theo dõi / cookie để biết người dùng đang làm gì trên chính trang đó, ví dụ, họ không được phép tìm hiểu ngân hàng nào tôi sử dụng, trường con tôi học, v.v ... Do đó, các trình duyệt sẽ không cho phép truy cập vào tài sản đó
McAden

84

Có một cách khác để kiểm tra - kiểm tra người giới thiệu. Trang đầu tiên thường sẽ có một người giới thiệu trống ...

if (document.referrer == "") {
    window.close()
} else {
    history.back()
}

2
Giới thiệu có thể được ẩn vì lý do riêng tư.
Kornel

11
Giới thiệu luôn trống khi một trang không được tải bởi một liên kết mà bằng cách nhập URL vào thanh địa chỉ hoặc tải dấu trang. Các trang như vậy có thể chắc chắn có một lịch sử, khi tab / cửa sổ trình duyệt đã tải một trang khác trước đó!
ygoe

1
Nhưng là giải pháp áp dụng để điều hướng trên trang web đa trang
Dan

36
Không hoạt động nếu một cửa sổ được mở bằng target = "_ blank" để buộc một cửa sổ mới. Nút quay lại trên trình duyệt sẽ không hoạt động, nhưng sẽ có một tài
liệu.referrer

3
Điều này sẽ không hoạt động nếu bạn đang đi từ một trang an toàn (HTTPS) đến một trang không an toàn (HTTP), vì điều đó sẽ loại bỏ người giới thiệu.
Kevin

54

Mã của tôi cho phép trình duyệt quay lại một trang và nếu thất bại, nó sẽ tải một url dự phòng. Nó cũng phát hiện các thay đổi hashtags.

Khi nút quay lại không khả dụng, url dự phòng sẽ được tải sau 500 ms, do đó trình duyệt có đủ thời gian để tải trang trước đó. Tải url dự phòng ngay sau window.history.go(-1);đó sẽ khiến trình duyệt sử dụng url dự phòng, vì tập lệnh js chưa dừng lại.

function historyBackWFallback(fallbackUrl) {
    fallbackUrl = fallbackUrl || '/';
    var prevPage = window.location.href;

    window.history.go(-1);

    setTimeout(function(){ 
        if (window.location.href == prevPage) {
            window.location.href = fallbackUrl; 
        }
    }, 500);
}

6
Tôi nghĩ rằng điều này thực sự đóng đinh vào trung tâm của câu hỏi, tại sao một người quan tâm và những gì thực sự có thể được thực hiện về nó một cách đáng tin cậy và nhất quán.
Chris Marisic

1
Điều này hoạt động cho đến khi tôi lấy url nơi nút quay lại nằm và dán nó trong một tab mới bằng chrome. Nhấp vào nút quay lại dẫn đến việc được gửi đến một tab trống. :(
karlingen

2
Đó là hành vi mặc định của Chrome. Bạn "truy cập" trang chrome://newtabvà do đó bạn có thể quay lại lịch sử.
redelschaap

Cẩn thận với điều này bởi vì với kết nối mạng chậm, bạn sẽ truy cập url dự phòng khá thường xuyên.
cameck

14

Đây là cách tôi đã làm nó.

Tôi đã sử dụng sự kiện 'beforeunload' để đặt boolean. Sau đó, tôi đặt thời gian chờ để xem nếu 'tải trước' bị bắn.

var $window = $(window),
    $trigger = $('.select_your_link'),
    fallback = 'your_fallback_url';
    hasHistory = false;

$window.on('beforeunload', function(){
    hasHistory = true;
});

$trigger.on('click', function(){

    window.history.go(-1);

    setTimeout(function(){
        if (!hasHistory){
            window.location.href = fallback;
        }
    }, 200);

    return false;
});

Có vẻ như hoạt động trong các trình duyệt chính (đã thử nghiệm FF, Chrome, IE11 cho đến nay).


1
Đây là câu trả lời tốt nhất cho câu hỏi. Bạn có thể dễ dàng thay thế window.location.href = fallbackbằng window.close()và nó hoạt động quá.
Vitani

13

Có một đoạn tôi sử dụng trong các dự án của mình:

function back(url) {
    if (history.length > 2) {
        // if history is not empty, go back:
        window.History.back();
    } else if (url) {
        // go to specified fallback url:
        window.History.replaceState(null, null, url);
    } else {
        // go home:
        window.History.replaceState(null, null, '/');
    }
}

FYI: Tôi sử dụng History.js để quản lý lịch sử trình duyệt.


Tại sao để so sánh history.length với số 2?

Bởi vì trang bắt đầu của Chrome được tính là mục đầu tiên trong lịch sử của trình duyệt.


Có một vài khả năng history.lengthvà hành vi của người dùng:

  • Người dùng mở tab trống mới trong trình duyệt và sau đó chạy một trang. history.length = 2và chúng tôi muốn tắt back()trong trường hợp này, vì người dùng sẽ chuyển đến tab trống.
  • Người dùng mở trang trong tab mới bằng cách nhấp vào liên kết ở đâu đó trước đó. history.length = 1và một lần nữa chúng tôi muốn vô hiệu hóa back()phương thức.
  • Và cuối cùng, người dùng hạ cánh tại trang hiện tại sau khi tải lại vài trang . history.length > 2và bây giờ back()có thể được kích hoạt.

Lưu ý: Tôi bỏ qua trường hợp khi người dùng hạ cánh tại trang hiện tại sau khi nhấp vào liên kết từ trang web bên ngoài mà không có target="_blank".

Lưu ý 2: document.referrer trống khi bạn mở trang web bằng cách nhập địa chỉ của trang đó và cả khi trang web sử dụng ajax để tải trang con, vì vậy tôi đã ngừng kiểm tra giá trị này trong trường hợp đầu tiên.


Cách tiếp cận này làm việc rất tốt cho tôi. Tôi thực sự lưu trữ các liên kết dự phòng tĩnh cho các trang của tôi mà tôi sử dụng trên dự phòng.
Greg Blass

Nhưng, nếu bạn quay lại, lịch sử.length sẽ không thay đổi .. Vì vậy, nó không hoạt động đúng
Ciprian Mộcanu

Bạn nói đúng, thật không may. Tôi chỉ sử dụng đoạn mã này với cấu trúc "lùi một bước" chỉ có thể
gregmatys

12

điều này dường như để thực hiện các mẹo:

function goBackOrClose() {  

    window.history.back();
    window.close(); 

    //or if you are not interested in closing the window, do something else here
    //e.g. 
    theBrowserCantGoBack();

}

Gọi history.back () và sau đó window.c Đóng (). Nếu trình duyệt có thể quay lại lịch sử, nó sẽ không thể đưa ra tuyên bố tiếp theo. Nếu nó không thể quay lại, nó sẽ đóng cửa sổ.

Tuy nhiên, xin lưu ý rằng nếu trang đã đạt được bằng cách nhập một url, thì firefox sẽ không cho phép tập lệnh đóng cửa sổ.


3
Tôi đã thấy điều này không hoạt động trừ khi tôi sử dụng setTimeout với độ trễ vài trăm mili giây hoặc lâu hơn trước khi thử chạy câu lệnh tiếp theo, nếu không nó sẽ chạy sau khi chạy history.back ()
Ken Fehling

Tôi chưa từng trải nghiệm cá nhân, đó là trình duyệt nào?
xtrahelp.com

Tôi đã làm việc tốt với chức năng setTimeout trong câu trả lời dưới đây. ví dụ: setTimeout (function () {window.c Đóng ()}, 400);
gilchris

2
window.close()được coi là một rủi ro bảo mật bởi nhiều trình duyệt hiện đại. Một số sẽ không cho phép bạn làm điều đó.
Rudi Kershaw

bạn có thể làm bất cứ điều gì sau window.history.back (); window.c Đóng (); chỉ là một ví dụ
hariszaman

9

Bạn không thể trực tiếp kiểm tra xem nút quay lại có thể sử dụng được không. Bạn có thể nhìn vào history.length>0, nhưng điều đó sẽ đúng nếu có các trang trước trang hiện tại. Bạn chỉ có thể chắc chắn rằng nút quay lại không sử dụng được khi history.length===0.

Nếu điều đó không đủ tốt, về tất cả những gì bạn có thể làm là gọi history.back()và nếu trang của bạn vẫn được tải sau đó, nút quay lại không khả dụng! Tất nhiên điều đó có nghĩa nếu nút quay lại có sẵn, bạn vừa điều hướng khỏi trang. Bạn không được phép hủy điều hướng onunload, vì vậy, tất cả những gì bạn có thể làm để ngăn chặn việc quay lại thực sự xảy ra là trả lại một cái gì đó onbeforeunload, điều này sẽ dẫn đến một dấu nhắc khó chịu lớn xuất hiện. Nó không đáng.

Trên thực tế, đó thường là một ý tưởng thực sự tồi tệ để làm bất cứ điều gì với lịch sử. Điều hướng lịch sử là dành cho trình duyệt chrome, không phải trang web. Thêm các liên kết trở lại, các liên kết khác thường khiến nhiều người dùng nhầm lẫn hơn giá trị của nó.


2
về độ dài - thậm chí sau đó trong tất cả các trình duyệt. Một số trình duyệt tính trang hiện tại là mục lịch sử và bắt đầu từ 1. Bạn phải bao gồm phát hiện trình duyệt.
McAden

Thật ra tôi nghĩ nó luôn như 1vậy! Đây 0là một bộ não, tôi nghĩ rằng các trình duyệt sẽ luôn đáp ứng với 1hoặc nhiều hơn nữa. Hóa ra Opera và IE nghĩ khác là bắt tốt.
bobince

1
"Điều hướng lịch sử là dành cho trình duyệt chrome, không phải trang web" - Đồng ý
Brian

9

Hãy cẩn thận window.history.lengthvì nó cũng bao gồm các mục chowindow.history.forward()

Vì vậy, bạn có thể có window.history.lengthnhiều hơn 1 mục, nhưng không có mục nào trong lịch sử. Điều này có nghĩa là không có gì xảy ra nếu bạn bắnwindow.history.back()


5

history.lengthlà vô ích vì nó không hiển thị nếu người dùng có thể quay lại lịch sử. Ngoài ra các trình duyệt khác nhau sử dụng các giá trị ban đầu 0 hoặc 1 - nó phụ thuộc vào trình duyệt.

Giải pháp hoạt động là sử dụng $(window).on('beforeunload'sự kiện, nhưng tôi không chắc rằng nó sẽ hoạt động nếu trang được tải qua ajax và sử dụng PushState để thay đổi lịch sử cửa sổ.

Vì vậy, tôi đã sử dụng giải pháp tiếp theo:

var currentUrl = window.location.href;
window.history.back();
setTimeout(function(){
    // if location was not changed in 100 ms, then there is no history back
    if(currentUrl === window.location.href){
        // redirect to site root
        window.location.href = '/';
    }
}, 100);

Hoạt động với tôi như thế này: function goBackOrTo (targetUrl) {var currentUrl = window.location.href; cửa sổ.history.go (-1); setTimeout (function () {// nếu vị trí không được thay đổi trong 800 ms, thì sẽ không có lịch sử trở lại if (currentUrl === window.location.href) {// chuyển hướng đến trang web root window.location.href = targetUrl; }}, 800); }
alfonx 27/2/2015

2

Tôi đã đưa ra cách tiếp cận sau đây. Nó sử dụng sự kiện onb Beforeunload để phát hiện xem trình duyệt có bắt đầu rời khỏi trang hay không. Nếu nó không trong một khoảng thời gian nhất định, nó sẽ chỉ chuyển hướng đến dự phòng.

var goBack = function goBack(fallback){
    var useFallback = true;

    window.addEventListener("beforeunload", function(){
      useFallback = false;
    });

    window.history.back();

    setTimeout(function(){
        if (useFallback){ window.location.href = fallback; }
    }, 100); 
}

Bạn có thể gọi chức năng này bằng cách sử dụng goBack("fallback.example.org").


1
Tôi thích điều này nhất, tôi chỉ thay đổi windows.onbeforeunloadthành trình nghe sự kiện window.addEventListener("beforeunload", function (event) { useFallback = false; });để nó không ghi đè lên window.onb Beforeunload.
MiChAeLoKGB

2

Xây dựng trên câu trả lời ở đâyở đây . Tôi nghĩ rằng, câu trả lời kết luận hơn chỉ là để kiểm tra xem đây có phải là một trang mới trong một tab mới hay không.

Nếu lịch sử của trang nhiều hơn một, thì chúng ta có thể quay lại trang trước trang hiện tại. Nếu không, tab là một tab mới được mở và chúng ta cần tạo một tab mới.

Khác nhau, với các câu trả lời được liên kết, chúng tôi không kiểm tra vì một referrertab mới vẫn sẽ có một người giới thiệu.

if(1 < history.length) {
    history.back();
}
else {
    window.close();
}

1
Cảm ơn bạn. Bạn đã lưu ngày của tôi :).
Bijay Yadav

1

Có một giải pháp gần hoàn hảo khác, được lấy từ một câu trả lời SO khác :

if( (1 < history.length) && document.referrer ) {
    history.back();
}
else {
    // If you can't go back in history, you could perhaps close the window ?
    window.close();
}

Ai đó đã báo cáo rằng nó không hoạt động khi sử dụng target="_blank"nhưng dường như nó hoạt động với tôi trên Chrome.


0

trình duyệt có nút quay lại và chuyển tiếp. Tôi đưa ra một giải pháp cho câu hỏi này. nhưng nó sẽ ảnh hưởng đến hành động chuyển tiếp của trình duyệt và gây ra lỗi với một số trình duyệt.

Nó hoạt động như thế: Nếu trình duyệt mở một url mới, chưa bao giờ mở, history.length sẽ được phát triển.

để bạn có thể thay đổi hàm băm như

  location.href = '#__transfer__' + new Date().getTime() 

để có được một url không bao giờ được hiển thị, thì history.length sẽ có được độ dài thực sự.

  var realHistoryLength = history.length - 1

nhưng, nó không phải lúc nào cũng hoạt động tốt và tôi không biết tại sao, đặc biệt là khi url tự động nhảy nhanh.


0

Tôi đã cố gắng tìm một giải pháp và đây là giải pháp tốt nhất tôi có thể nhận được (nhưng hoạt động rất tốt và đó là giải pháp đơn giản nhất tôi đã tìm thấy ngay cả ở đây).

Trong trường hợp của tôi, tôi muốn quay lại lịch sử bằng nút quay lại, nhưng nếu trang đầu tiên người dùng mở là một trang con của ứng dụng của tôi, nó sẽ quay trở lại trang chính.

Giải pháp là, ngay sau khi ứng dụng được tải, tôi mới thay thế trạng thái lịch sử:

history.replaceState( {root: true}, '', window.location.pathname + window.location.hash)

Bằng cách này, tôi chỉ cần kiểm tra history.state.roottrước khi quay trở lại. Nếu đúng, tôi sẽ thay thế lịch sử:

if(history.state && history.state.root)
    history.replaceState( {root: true}, '', '/')
else
    history.back() 

Tôi không nghĩ có trường hợp sử dụng tốt khác. Có lẽ không phải là một ý tưởng tốt Nếu bạn muốn kiểm tra lịch sử bên ngoài ứng dụng của mình.
Maxwell sc

-1
var fallbackUrl = "home.php";
if(history.back() === undefined)
    window.location.href = fallbackUrl;

Điều này có vẻ siêu dễ dàng?! nó đã được thử nghiệm trên các trình duyệt khác nhau?
benzkji

trong Chrome history.back()undefinedduy nhất trên trang tab trống
gregmatys

-2

Giải pháp

'use strict';
function previousPage() {
  if (window.location.pathname.split('/').filter(({ length }) => length > 0).length > 0) {
    window.history.back();
  }
}

Giải thích

window.location.pathnamesẽ cung cấp cho bạn URI hiện tại. Ví dụ https://domain/question/1234/i-have-a-problemsẽ cho /question/1234/i-have-a-problem. Xem tài liệu về window.location để biết thêm thông tin.

Tiếp theo, lời kêu gọi split()sẽ cung cấp cho chúng ta tất cả các đoạn của URI đó. vì vậy nếu chúng ta lấy URI trước đó, chúng ta sẽ có một cái gì đó như thế ["", "question", "1234", "i-have-a-problem"]. Xem tài liệu về String.prototype.split () để biết thêm thông tin.

Cuộc gọi đến filter()ở đây để lọc chuỗi trống được tạo bởi dấu gạch chéo ngược. Về cơ bản, nó sẽ chỉ trả về URI đoạn có độ dài lớn hơn 1 (chuỗi không trống). Vì vậy, chúng tôi sẽ có một cái gì đó như ["question", "1234", "i-have-a-question"]. Điều này có thể đã được viết như vậy:

'use strict';
window.location.pathname.split('/').filter(function(fragment) {
  return fragment.length > 0;
});

Xem tài liệu về Array.prototype.filter ()bài tập Hủy cấu trúc để biết thêm thông tin.

Bây giờ, nếu người dùng cố gắng quay lại trong khi đang bật https://domain/, chúng tôi sẽ không kích hoạt câu lệnh if và vì vậy sẽ không kích hoạt window.history.back()phương thức để người dùng sẽ ở lại trang web của chúng tôi. URL này sẽ tương đương với URL []có độ dài 00 > 0sai. Do đó, âm thầm thất bại. Tất nhiên, bạn có thể đăng nhập một cái gì đó hoặc có một hành động khác nếu bạn muốn.

'use strict';
function previousPage() {
  if (window.location.pathname.split('/').filter(({ length }) => length > 0).length > 0) {
    window.history.back();
  } else {
    alert('You cannot go back any further...');
  }
}

Hạn chế

Tất nhiên, giải pháp này sẽ không hoạt động nếu trình duyệt không hỗ trợ API Lịch sử . Kiểm tra tài liệu để biết thêm về nó trước khi sử dụng giải pháp này.


-5

Tôi không chắc chắn nếu điều này hoạt động và nó hoàn toàn chưa được kiểm tra, nhưng hãy thử điều này:

<script type="text/javascript">

    function goBack() {
        history.back();
    }

    if (history.length > 0) { //if there is a history...
        document.getElementsByTagName('button')[].onclick="goBack()"; //assign function "goBack()" to all buttons onClick
    } else {
        die();
    }
</script>

Và một nơi nào đó trong HTML:

<button value="Button1"> //These buttons have no action
<button value="Button2">

BIÊN TẬP:

Những gì bạn cũng có thể làm là nghiên cứu những trình duyệt nào hỗ trợ chức năng quay lại (tôi nghĩ tất cả đều làm được) và sử dụng đối tượng phát hiện trình duyệt JavaScript tiêu chuẩn được tìm thấy và mô tả kỹ lưỡng trên trang này . Sau đó, bạn có thể có 2 trang khác nhau: một cho "trình duyệt tốt" tương thích với nút quay lại và một cho "trình duyệt xấu" bảo họ cập nhật trình duyệt của họ


2
history.backlà một chức năng. Bạn muốn kiểm tra xem history.length > 0sau đó nếu nó quay trở lại vớihistory.back()
bộ mã hóa pixl

3
Ngoài ra, []trên NodeList không có ý nghĩa gì và bạn không thể gán một chuỗi cho một trình xử lý sự kiện.
bobince

-8

Kiểm tra nếu window.history.lengthbằng 0.


6
Không phải là một cách hay, vì history.length không cho bạn biết bạn đang ở đâu trong lịch sử ...
Ron Reiter

@Ron Reiter: Vâng, tôi nghĩ rằng câu trả lời hàng đầu và những bình luận khác cho câu hỏi này đã được thiết lập từ hơn một năm trước ...
Cristian Sanchez
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.