Jak sprawdzić, czy użytkownik może wrócić do historii przeglądarki, czy nie

Odpowiedzi:

119

Krótka odpowiedź: nie możesz.

Technicznie istnieje dokładny sposób, którym byłoby sprawdzenie nieruchomości:

history.previous

Jednak to nie zadziała. Problem polega na tym, że w większości przeglądarek jest to uważane za naruszenie bezpieczeństwa i zwykle zwraca wartość undefined .

history.length

Jest to właściwość, którą sugerowali inni ...
Jednak długość nie działa całkowicie, ponieważ nie wskazuje, w którym miejscu historii jesteś. Ponadto nie zawsze zaczyna się od tego samego numeru. Na przykład przeglądarka, która nie ma strony docelowej, zaczyna się od 0, a inna przeglądarka, która korzysta ze strony docelowej, zaczyna się od 1.

tekst alternatywny

W większości przypadków dodawane jest łącze, które wywołuje:

history.back();

lub

 history.go(-1);

i oczekuje się, że jeśli nie możesz wrócić, kliknięcie linku nic nie da.

McAden
źródło
To dobra informacja, ale nie rozwiązuje problemu. Byłoby to opracowanie kodu, który faktycznie działa w każdej przeglądarce. Być może kod, który najpierw sprawdza przeglądarkę, której używasz.
Santiago Bendavid
5
Mówię, że nie ma ostatecznej odpowiedzi. Mówisz o zaletach i wadach każdego podejścia, ale nie mówisz o tym, jak uzyskać skrypt, który sprawdza, jakiej przeglądarki używasz i warunkowo wykonuje jeden lub drugi fragment kodu.
Santiago Bendavid
Czy mogę wiedzieć, co masz na myśli, mówiąc: „Problem polega na tym, że w większości przeglądarek jest to uznawane za naruszenie bezpieczeństwa”. Inny użytkownik w innym wątku również wskazał, że możliwość uzyskania historii przeglądarki klienta narusza bezpieczeństwo, ale nie wyjaśnia dlaczego. Czy ktoś może podać przykład, jakie są zagrożenia bezpieczeństwa?
Kevin Chandra
Witryna internetowa nie powinna być w stanie poznać historii użytkownika, która może zawierać pośrednie dane osobowe. Witryna może korzystać ze śledzenia / plików cookie, aby wiedzieć, co robi użytkownik w samej witrynie, ale na przykład nie powinna mieć możliwości dowiedzenia się, z jakiego banku korzystam, do której szkoły chodzą moje dzieci itp. Dlatego przeglądarki nie pozwolą na dostęp do tej własności
McAden
84

Jest inny sposób sprawdzenia - sprawdź stronę odsyłającą. Pierwsza strona zwykle będzie miała pustą stronę odsyłającą ...

if (document.referrer == "") {
    window.close()
} else {
    history.back()
}
Ron Reiter
źródło
2
Strona odsyłająca może zostać ukryta ze względu na ochronę prywatności.
Kornel
11
Strona odsyłająca jest zawsze pusta, gdy strona nie została załadowana przez łącze, ale po wprowadzeniu adresu URL w pasku adresu lub załadowaniu zakładki. Takie strony mogą jednak z pewnością mieć historię, gdy karta / okno przeglądarki ładowało wcześniej inną stronę!
ygoe
1
Ale jest odpowiednie rozwiązanie do nawigacji w witrynie wielostronicowej
Dan
36
Nie działa, jeśli okno zostało otwarte z target = "_ blank", aby wymusić nowe okno. Przycisk Wstecz w przeglądarce nie będzie działać, ale pojawi się document.referrer
Mike_K
3
To nie zadziała, jeśli przechodzisz z bezpiecznej (HTTPS) strony na niezabezpieczoną stronę (HTTP), ponieważ spowoduje to usunięcie strony odsyłającej.
Kevin Borders
54

Mój kod pozwala przeglądarce cofnąć się o jedną stronę, a jeśli to się nie powiedzie, ładuje zastępczy adres URL. Wykrywa również zmiany hashtagów.

Gdy przycisk Wstecz nie był dostępny, zastępczy adres URL zostanie załadowany po 500 ms, więc przeglądarka ma wystarczająco dużo czasu, aby załadować poprzednią stronę. Wczytanie zastępczego adresu URL zaraz po window.history.go(-1);tym spowodowałoby, że przeglądarka użyłaby zastępczego adresu URL, ponieważ skrypt js jeszcze się nie zatrzymał.

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);
}
redelschaap
źródło
6
Myślę, że to naprawdę trafia w sedno pytania, dlaczego dana osoba się tym przejmuje i co właściwie można z tym zrobić w sposób rzetelny i konsekwentny.
Chris Marisic,
1
Działało, dopóki nie wziąłem adresu URL, w którym znajduje się przycisk Wstecz, i nie wkleiłem go w nowej karcie w chrome. Kliknięcie przycisku Wstecz powodowało wysłanie do pustej karty. :(
karlingen
2
To domyślne zachowanie Chrome. „Odwiedziłeś” stronę chrome://newtabi dzięki temu możesz cofnąć się do historii.
redelschaap
Ostrożnie z tym, ponieważ przy wolnym połączeniu sieciowym dość regularnie trafisz na zastępczy adres URL.
cameck
14

Oto jak to zrobiłem.

Użyłem zdarzenie „beforeunload” ustawić wartość logiczną. Następnie ustawiłem limit czasu, aby sprawdzić, czy zadziałał komunikat „beforeunload”.

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;
});

Wydaje się działać w głównych przeglądarkach (do tej pory testowane FF, Chrome, IE11).

Toni Feistauer
źródło
1
To zdecydowanie najlepsza odpowiedź na to pytanie. Można łatwo wymienić window.location.href = fallbackz window.close()i działa zbyt.
Vitani
13

W moich projektach używam fragmentu kodu:

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, '/');
    }
}

Do Twojej wiadomości: Używam History.js do zarządzania historią przeglądarki.


Po co porównywać długość historii z liczbą 2?

Ponieważ strona początkowa Chrome jest liczona jako pierwsza pozycja w historii przeglądarki.


Możliwości history.lengthi zachowania użytkownika jest kilka:

  • Użytkownik otwiera nową pustą kartę w przeglądarce, a następnie uruchamia stronę. history.length = 2i chcemy wyłączyć back()w tym przypadku, ponieważ użytkownik przejdzie do pustej zakładki.
  • Użytkownik otwiera stronę w nowej karcie , klikając łącze gdzieś wcześniej. history.length = 1i znowu chcemy wyłączyć back()metodę.
  • I wreszcie, użytkownik trafia na bieżącą stronę po przeładowaniu kilku stron . history.length > 2a teraz back()można włączyć.

Uwaga: pomijam przypadek, gdy użytkownik wyląduje na bieżącej stronie po kliknięciu linku z zewnętrznej strony bez target="_blank".

Uwaga 2: document.referrer jest pusta, gdy otwierasz stronę internetową, wpisując jej adres, a także gdy strona używa Ajax do ładowania podstron, więc przestałem sprawdzać tę wartość w pierwszym przypadku.

gregmatys
źródło
To podejście zadziałało świetnie dla mnie. W rzeczywistości przechowuję statyczne linki rezerwowe do moich stron, których używam w przypadku rezerwy.
Greg Blass
Ale jeśli wrócisz, historia.length się nie zmieni .. Więc to nie działa poprawnie
Ciprian Mocanu
Niestety masz rację. Używam tego fragmentu
kodu
12

wydaje się, że to działa:

function goBackOrClose() {  

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

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

}

Wywołaj history.back (), a następnie window.close (). Jeśli przeglądarka jest w stanie wrócić do historii, nie będzie w stanie przejść do następnego zestawienia. Jeśli nie może się cofnąć, zamknie okno.

Należy jednak pamiętać, że jeśli strona została otwarta przez wpisanie adresu URL, firefox nie pozwoli skryptowi na zamknięcie okna.

xtrahelp.com
źródło
3
Zauważyłem, że to nie działa, chyba że użyję setTimeout z opóźnieniem kilkuset milisekund przed próbą uruchomienia następnej instrukcji, w przeciwnym razie zadziała i tak po uruchomieniu history.back ()
Ken Fehling
Nie doświadczyłem tego osobiście, która przeglądarka to była?
xtrahelp.com
Pracowałem dobrze z funkcją setTimeout w poniższej odpowiedzi. np .: setTimeout (function () {window.close ()}, 400);
gilchris,
2
window.close()jest uważany za zagrożenie bezpieczeństwa przez wiele nowoczesnych przeglądarek. Niektórzy po prostu nie pozwolą ci tego zrobić.
Rudi Kershaw
możesz zrobić wszystko po window.history.back (); window.close (); to tylko przykład
hariszaman
10

Uważaj, window.history.lengthponieważ zawiera również wpisy dlawindow.history.forward()

Możesz więc mieć może window.history.lengthwięcej niż 1 wpisy, ale bez wpisów historii. Oznacza to, że nic się nie dzieje, gdy strzelaszwindow.history.back()

Blitzlord
źródło
9

Nie możesz bezpośrednio sprawdzić, czy przycisk Wstecz jest użyteczny. Możesz na nie spojrzeć history.length>0, ale będzie to prawdą, jeśli przed bieżącą stroną są również strony. Możesz mieć pewność, że przycisk Wstecz jest bezużyteczny tylko wtedy, gdy history.length===0.

Jeśli to nie wystarczy, prawie wszystko, co możesz zrobić, to zadzwonić, history.back()a jeśli strona jest nadal ładowana, przycisk Wstecz jest niedostępny! Oczywiście oznacza to, że jeśli przycisk Wstecz jest dostępny, właśnie opuściłeś stronę. Nie możesz anulować nawigacji w programie onunload, więc wszystko, co możesz zrobić, aby zatrzymać faktycznie dzieje się z powrotem, to zwrócić coś z onbeforeunload, co spowoduje pojawienie się dużego irytującego monitu. To nie jest tego warte.

W rzeczywistości robienie czegokolwiek z historią to naprawdę zły pomysł. Nawigacja w historii dotyczy przeglądarki Chrome, a nie stron internetowych. Dodawanie linków „wróć” zazwyczaj powoduje więcej dezorientacji użytkowników, niż jest to warte.

bobince
źródło
2
jeśli chodzi o długość - nawet wtedy nie we wszystkich przeglądarkach. Niektóre przeglądarki liczą bieżącą stronę jako element historii i rozpoczynają od 1. Konieczne byłoby uwzględnienie wykrywania przeglądarki.
McAden
Właściwie myślałem, że tak było zawsze 1! To 0był żart, myślałem, że przeglądarki zawsze będą reagować z 1lub więcej. Okazuje się, że Opera i IE myślą inaczej - dobry chwyt.
bobince
1
„Nawigacja w historii dotyczy przeglądarki Chrome, a nie stron internetowych” - Zgoda
Brian
5

history.lengthjest bezużyteczny, ponieważ nie pokazuje, czy użytkownik może cofnąć się w historii. Również różne przeglądarki używają początkowych wartości 0 lub 1 - zależy to od przeglądarki.

Działającym rozwiązaniem jest użycie $(window).on('beforeunload'zdarzenia, ale nie jestem pewien, czy zadziała, jeśli strona jest ładowana przez Ajax i używa pushState do zmiany historii okna.

Więc użyłem następnego rozwiązania:

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);
Gromo
źródło
U mnie działa tak: function goBackOrTo (targetUrl) {var currentUrl = window.location.href; window.history.go (-1); setTimeout (function () {// jeśli lokalizacja nie została zmieniona w ciągu 800 ms, to nie ma historii z powrotem if (currentUrl === window.location.href) {// przekierowanie do katalogu głównego witryny window.location.href = targetUrl; }}, 800); }
alfonx
2

Wymyśliłem następujące podejście. Wykorzystuje zdarzenie onbeforeunload do wykrywania, czy przeglądarka zaczyna opuszczać stronę, czy nie. Jeśli nie nastąpi to w określonym przedziale czasu, po prostu przekieruje do rozwiązania zastępczego.

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); 
}

Możesz wywołać tę funkcję za pomocą goBack("fallback.example.org").

Pascal Raszyk
źródło
1
Najbardziej podoba mi się to, po prostu zmieniłem windows.onbeforeunloadna detektor zdarzeń, window.addEventListener("beforeunload", function (event) { useFallback = false; });więc nie nadpisuje window.onbeforeunload.
MiChAeLoKGB
2

Opierając się na odpowiedzi tu i tutaj . Myślę, że bardziej rozstrzygającą odpowiedzią jest po prostu sprawdzenie, czy jest to nowa strona w nowej karcie.

Jeśli historia strony jest więcej niż jedna, możemy wrócić do strony poprzedniej do strony bieżącej. Jeśli nie, karta jest nowo otwartą kartą i musimy utworzyć nową kartę.

W przeciwieństwie do odpowiedzi, do których prowadzą linki, nie sprawdzamy, czy referrernowa karta nadal będzie miała odsyłacz.

if(1 < history.length) {
    history.back();
}
else {
    window.close();
}
atw
źródło
1
Dziękuję Ci. Uratowałeś mi dzień :).
Bijay Yadav
1

Istnieje inne prawie idealne rozwiązanie, zaczerpnięte z innej odpowiedzi SO :

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();
}

Ktoś zgłosił, że nie działa podczas używania, target="_blank"ale wydaje mi się, że działa u mnie na Chrome.

Yonn Trimoreau
źródło
0

przeglądarka ma przycisk Wstecz i Dalej. Znajduję rozwiązanie na to pytanie. ale wpłynie to na działanie przeglądarki i spowoduje błąd w niektórych przeglądarkach.

Działa to tak: jeśli przeglądarka otworzy nowy adres URL, który nigdy się nie otwierał, długość history.length wzrośnie.

więc możesz zmienić haszysz

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

aby uzyskać nigdy nie wyświetlany adres URL, wówczas history.length otrzyma prawdziwą długość.

  var realHistoryLength = history.length - 1

ale nie zawsze to działa dobrze i nie wiem dlaczego, zwłaszcza gdy szybko przeskakuje adres URL.

Honchy gan
źródło
0

Próbowałem znaleźć rozwiązanie i to jest najlepsze, jakie mogłem dostać (ale działa świetnie i jest to najłatwiejsze rozwiązanie, jakie znalazłem nawet tutaj).

W moim przypadku chciałem wrócić do historii za pomocą przycisku Wstecz, ale jeśli pierwsza strona, którą otworzył użytkownik, była podstroną mojej aplikacji, wróciłby do strony głównej.

Rozwiązaniem było to, że gdy tylko aplikacja zostanie załadowana, właśnie zmieniłem stan historii:

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

W ten sposób muszę tylko sprawdzić history.state.rootprzed powrotem. Jeśli tak, zastępuję historię:

if(history.state && history.state.root)
    history.replaceState( {root: true}, '', '/')
else
    history.back() 
Maxwell sc
źródło
Nie sądzę, że istnieje inny dobry przypadek użycia. Może nie jest to dobry pomysł, jeśli chcesz sprawdzić historię poza aplikacją.
Maxwell sc
-1
var fallbackUrl = "home.php";
if(history.back() === undefined)
    window.location.href = fallbackUrl;
Rejeesh Prarath
źródło
wygląda to super łatwe ?! czy jest testowany w różnych przeglądarkach?
benzkji,
w Chrome history.back()jest undefinedtylko na pustej stronie karty
gregmatys
-2

Rozwiązanie

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

Wyjaśnienie

window.location.pathnamepoda aktualny identyfikator URI. Na przykład https://domain/question/1234/i-have-a-problemda /question/1234/i-have-a-problem. Zobacz dokumentację o window.location, aby uzyskać więcej informacji.

Następnie wywołanie split()dostarczy nam wszystkie fragmenty tego identyfikatora URI. więc jeśli weźmiemy nasz poprzedni URI, będziemy mieć coś takiego ["", "question", "1234", "i-have-a-problem"]. Zobacz dokumentację o String.prototype.split (), aby uzyskać więcej informacji.

Wywołanie filter()jest tutaj, aby odfiltrować pusty ciąg wygenerowany przez lewy ukośnik. Zasadniczo zwróci tylko fragment URI, który ma długość większą niż 1 (niepusty ciąg). Więc mielibyśmy coś takiego ["question", "1234", "i-have-a-question"]. Można to napisać tak:

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

Zobacz dokumentację o Array.prototype.filter () i przypisaniu Destrukturyzacja, aby uzyskać więcej informacji.

Teraz, jeśli użytkownik spróbuje wrócić, będąc włączony https://domain/, nie uruchomimy instrukcji if, a więc nie uruchomimy window.history.back()metody, więc użytkownik pozostanie w naszej witrynie. Ten adres URL będzie odpowiednikiem tego, []który ma długość 0i 0 > 0jest fałszywy. Dlatego cicho zawodzi. Oczywiście, jeśli chcesz, możesz coś zarejestrować lub wykonać inną akcję.

'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...');
  }
}

Ograniczenia

Oczywiście to rozwiązanie nie zadziała, jeśli przeglądarka nie obsługuje History API . Przed użyciem tego rozwiązania zapoznaj się z dokumentacją, aby dowiedzieć się więcej na ten temat.

Amin NAIRI
źródło
-5

Nie jestem pewien, czy to działa i jest całkowicie nieprzetestowane, ale spróbuj tego:

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

I gdzieś w HTML:

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

EDYTOWAĆ:

Możesz również sprawdzić, jakie przeglądarki obsługują funkcję wsteczną (myślę, że wszystkie tak robią) i użyć standardowego obiektu wykrywania przeglądarki JavaScript, który został znaleziony i dokładnie opisany na tej stronie . Następnie możesz mieć 2 różne strony: jedną dla „dobrych przeglądarek” zgodną z przyciskiem Wstecz i jedną dla „złych przeglądarek” z poleceniem zaktualizowania przeglądarki

Latze
źródło
2
history.backjest funkcją. Chcesz sprawdzić, history.length > 0czy to wróci zhistory.back()
pixl coder
3
Również []na NodeList nie ma sensu i nie można przypisać ciągu do procedury obsługi zdarzeń.
bobince
-8

Sprawdź, czy window.history.lengthjest równe 0.

Cristian Sanchez
źródło
6
Nie jest to dobry sposób, ponieważ history.length nie mówi ci, gdzie jesteś w historii ...
Ron Reiter
@Ron Reiter: Tak, myślę, że najlepsza odpowiedź i inne komentarze na to pytanie ustaliły już, że ponad rok temu ...
Cristian Sanchez