it-swarm.com.de

So ermitteln Sie das Browser-Back-Button-Ereignis - Cross Browser

Wie erkennen Sie definitiv, ob der Benutzer im Browser die Zurück-Taste gedrückt hat oder nicht? 

Wie erzwingen Sie die Verwendung einer In-Page-Zurück-Schaltfläche in einer einseitigen Webanwendung mithilfe eines #URL-Systems? 

Warum in aller Welt können Browser-Buttons nicht ihre eigenen Ereignisse auslösen !?

147
Xarus

(Hinweis: Gemäß Sharkys Feedback habe ich Code zum Erkennen von Backspaces hinzugefügt.)

Ich habe diese Fragen daher häufig zu SO gesehen und bin kürzlich auf das Problem der Steuerung der Back-Button-Funktionalität gestoßen. Nach ein paar Tagen der Suche nach der besten Lösung für meine Anwendung (Einzelne Seite mit Hash-Navigation) habe ich ein einfaches, browserübergreifendes, bibliotheksloses System zum Erkennen der Zurück-Taste gefunden.

Die meisten Leute empfehlen die Verwendung von:

window.onhashchange = function() {
 //blah blah blah
}

Diese Funktion wird jedoch auch aufgerufen, wenn ein Benutzer ein In-Page-Element verwendet, das den Ortshash ändert. Nicht die beste Benutzererfahrung, wenn Ihr Benutzer klickt und die Seite vor oder zurück geht.

Um Ihnen einen Überblick über mein System zu geben, fülle ich ein Array mit vorherigen Hashwerten auf, während sich mein Benutzer durch die Benutzeroberfläche bewegt. Es sieht ungefähr so ​​aus:

function updateHistory(curr) {
    window.location.lasthash.Push(window.location.hash);
    window.location.hash = curr;
}

Ziemlich einfach. Ich mache dies, um die Browser-übergreifende Unterstützung sowie die Unterstützung älterer Browser sicherzustellen. Übergeben Sie einfach den neuen Hash an die Funktion und er speichert ihn für Sie und ändert dann den Hash (der dann in die Browser-Historie eingefügt wird).

Ich verwende auch eine In-Page-Zurück-Schaltfläche, mit der der Benutzer mithilfe des lasthash-Arrays zwischen den Seiten bewegt wird. Es sieht aus wie das:

function goBack() {
    window.location.hash = window.location.lasthash[window.location.lasthash.length-1];
    //blah blah blah
    window.location.lasthash.pop();
}

Dadurch wird der Benutzer auf den letzten Hash zurückgesetzt und der letzte Hash wird aus dem Array entfernt (ich habe jetzt keinen Vorwärtsknopf).

So. Wie erkenne ich, ob ein Benutzer meine In-Page-Zurück-Schaltfläche oder die Browser-Schaltfläche verwendet hat?

Zuerst habe ich mir window.onbeforeunload angesehen, aber es hat keinen Erfolg - das wird nur dann aufgerufen, wenn der Benutzer die Seiten wechselt. Dies geschieht nicht in einer Einzelseitenanwendung, die die Hashnavigation verwendet.

Nach einigen weiteren Eingrabungen sah ich also Empfehlungen, wie man eine Flag-Variable setzen konnte. In meinem Fall besteht das Problem darin, dass ich versuchen würde, es festzulegen, aber da alles asynchron ist, wird es nicht immer rechtzeitig für die if-Anweisung in der Hash-Änderung festgelegt. .onMouseDown wurde nicht immer in Click aufgerufen, und das Hinzufügen zu einem Onclick würde es niemals schnell genug auslösen.

Zu diesem Zeitpunkt habe ich den Unterschied zwischen document und window untersucht. Meine letzte Lösung bestand darin, das Flag mit document.onmouseover zu setzen und es mit document.onmouseleave zu deaktivieren.

Was passiert, ist, dass, während sich die Maus des Benutzers im Dokumentbereich befindet (lesen Sie: die gerenderte Seite, jedoch den Browserrahmen nicht), mein Boolean auf true gesetzt ist. Sobald die Maus den Dokumentbereich verlässt, wechselt der Boolean zu false.

Auf diese Weise kann ich meinen window.onhashchange ändern in:

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

Sie werden die Prüfung auf #undefined feststellen. Wenn in meinem Array kein Verlauf verfügbar ist, wird undefined zurückgegeben. Ich frage den Benutzer, ob er das Ereignis window.onbeforeunload verwenden möchte.

Kurz gesagt, und für Personen, die nicht unbedingt eine In-Page-Zurück-Schaltfläche oder ein Array verwenden, um den Verlauf zu speichern:

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

Und da hast du es. Eine einfache, dreiteilige Methode zum Erkennen der Verwendung von Zurückschaltflächen gegen In-Page-Elemente in Bezug auf die Hashnavigation.

BEARBEITEN:

Um sicherzustellen, dass der Benutzer nicht die Rücktaste zum Auslösen des back -Ereignisses verwendet, können Sie Folgendes hinzufügen (Danke an @thetoolman für diese Frage ):

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

Sie können den Event-Handler popstate versuchen, z.

window.addEventListener('popstate', function(event) {
    // The popstate event is fired each time when the current history entry changes.

    var r = confirm("You pressed a Back button! Are you sure?!");

    if (r == true) {
        // Call Back button programmatically as per user confirmation.
        history.back();
        // Uncomment below line to redirect to the previous page instead.
        // window.location = document.referrer // Note: IE11 is not supporting this.
    } else {
        // Stay on the current page.
        history.pushState(null, null, window.location.pathname);
    }

    history.pushState(null, null, window.location.pathname);

}, false);

Hinweis: Um optimale Ergebnisse zu erzielen, sollten Sie diesen Code nur auf bestimmten Seiten laden, auf denen Sie die Logik implementieren möchten, um andere unerwartete Probleme zu vermeiden.

Das Popstate-Ereignis wird jedes Mal ausgelöst, wenn sich der aktuelle Verlaufseintrag ändert (Benutzer navigiert in einen neuen Status). Dies geschieht, wenn der Benutzer auf die Zurück/Vorwärts-Schaltflächen des Browsers klickt oder wenn history.back(), history.forward(), history.go() Methoden programmatisch aufgerufen werden.

Die event.state-Eigenschaft des Ereignisses entspricht dem History-Status-Objekt.

Umwickeln Sie die Syntax jQuery (um den Listener hinzuzufügen, nachdem das Dokument fertig ist):

(function($) {
  // Above code here.
})(jQuery);

Siehe auch: window.onpopstate beim Laden der Seite


Siehe auch die Beispiele auf Single-Page-Apps und HTML5-pushState page:

<script>
// jQuery
$(window).on('popstate', function (e) {
    var state = e.originalEvent.state;
    if (state !== null) {
        //load content with ajax
    }
});

// Vanilla javascript
window.addEventListener('popstate', function (e) {
    var state = e.state;
    if (state !== null) {
        //load content with ajax
    }
});
</script>

Dies sollte mit Chrome 5+, Firefox 4+, IE 10+, Safari 6+, Opera 11.5+ und ähnlichen kompatibel sein.

53
kenorb

Ich hatte lange mit dieser Anforderung zu kämpfen und nahm einige der oben genannten Lösungen, um sie umzusetzen. Ich stolperte jedoch über eine Beobachtung und es scheint an Chrome, Firefox und Safari-Browsern + Android und iPhone zu funktionieren 

Auf Seite laden:

window.history.pushState({page: 1}, "", "");

window.onpopstate = function(event) {

  // "event" object seems to contain value only when the back button is clicked
  // and if the pop state event fires due to clicks on a button
  // or a link it comes up as "undefined" 

  if(event){
    // Code to handle back button or prevent from navigation
  }
  else{
    // Continue user action through link or button
  }
}

Lassen Sie mich wissen, ob das hilft. Wenn etwas fehlt, werde ich mich freuen zu verstehen.

11
Itzmeygu

In Javascript bedeutet der Navigationstyp 2, dass auf die Schaltfläche "Zurück" oder "Vorwärts" des Browsers geklickt wurde und der Browser tatsächlich Inhalte aus dem Cache nimmt.

if(performance.navigation.type == 2)
{
    //Do your code here
}
7
Hasan Badshah

Browser: https://jsfiddle.net/Limitlessisa/axt1Lqoz/

Für die mobile Steuerung: https://jsfiddle.net/Limitlessisa/axt1Lqoz/show/

$(document).ready(function() {
  $('body').on('click touch', '#share', function(e) {
    $('.share').fadeIn();
  });
});

// geri butonunu yakalama
window.onhashchange = function(e) {
  var oldURL = e.oldURL.split('#')[1];
  var newURL = e.newURL.split('#')[1];

  if (oldURL == 'share') {
    $('.share').fadeOut();
    e.preventDefault();
    return false;
  }
  //console.log('old:'+oldURL+' new:'+newURL);
}
.share{position:fixed; display:none; top:0; left:0; width:100%; height:100%; background:rgba(0,0,0,.8); color:white; padding:20px;
<!DOCTYPE html>
<html>

<head>
    <title>Back Button Example</title>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

</head>

<body style="text-align:center; padding:0;">
    <a href="#share" id="share">Share</a>
    <div class="share" style="">
        <h1>Test Page</h1>
        <p> Back button press please for control.</p>
    </div>
</body>

</html>
4
Limitless isa

Hier ist meine Meinung dazu. Die Annahme ist, wenn sich die URL ändert, aber kein Klick innerhalb der document erkannt wurde, ist dies ein Browser zurück (Ja oder Weiter). Ein Klick des Benutzers wird nach 2 Sekunden zurückgesetzt, damit dies auf Seiten funktioniert, die Inhalte über Ajax laden:

(function(window, $) {
  var anyClick, consoleLog, debug, delay;
  delay = function(sec, func) {
    return setTimeout(func, sec * 1000);
  };
  debug = true;
  anyClick = false;
  consoleLog = function(type, message) {
    if (debug) {
      return console[type](message);
    }
  };
  $(window.document).click(function() {
    anyClick = true;
    consoleLog("info", "clicked");
    return delay(2, function() {
      consoleLog("info", "reset click state");
      return anyClick = false;
    });
  });
  return window.addEventListener("popstate", function(e) {
    if (anyClick !== true) {
      consoleLog("info", "Back clicked");
      return window.dataLayer.Push({
        event: 'analyticsEvent',
        eventCategory: 'test',
        eventAction: 'test'
      });
    }
  });
})(window, jQuery);
2
TomTom101

Die richtige Antwort ist bereits vorhanden, um die Frage zu beantworten. Ich möchte die neue JavaScript-API erwähnen PerformanceNavigationTiming , sie ersetzt die veraltete performance.navigation .

Der folgende Code meldet sich in der Konsole "back_forward" an, wenn der Benutzer mit den Schaltflächen "Zurück" oder "Vorwärts" auf Ihrer Seite gelandet ist. Sehen Sie sich die Kompatibilitätstabelle an, bevor Sie sie in Ihrem Projekt verwenden.

var perfEntries = performance.getEntriesByType("navigation");
for (var i = 0; i < perfEntries.length; i++) {
    console.log(perfEntries[i].type);
}
1
llaaalu

Ich habe diese Aufgabe mit dem folgenden Trick erledigt. Mit diesem hinzugefügten Ereignis-Listener, der aufgerufen wird, wenn jemand mit dem Zurück-Button des Browsers zur Seite zurückkehrt und bei diesem Ereignis die Seite einfach neu lädt. Hoffentlich hilft das.

window.addEventListener("pageshow", function(event) {
  var historyTraversal = event.persisted || (typeof window.performance !=
    "undefined" && window.performance.navigation.type === 2);
  if (historyTraversal) {
    // Handle page restore. 
    window.location.reload();
  }
});

hat diesen Code am Ende der Seite hinzugefügt.

1
mohitesachin217

Ich konnte einige der Antworten in diesem Thread und andere verwenden, um es in IE und Chrome/Edge zum Laufen zu bringen. history.pushState für mich wurde in IE11 nicht unterstützt.

if (history.pushState) {
    //Chrome and modern browsers
    history.pushState(null, document.title, location.href);
    window.addEventListener('popstate', function (event) {
        history.pushState(null, document.title, location.href);
    });
}
else {
    //IE
    history.forward();
}
1

Der document.mouseover funktioniert nicht für IE und FireFox . Allerdings habe ich Folgendes versucht:

$(document).ready(function () {
  setInterval(function () {
    var $sample = $("body");
    if ($sample.is(":hover")) {
      window.innerDocClick = true;
    } else {
      window.innerDocClick = false;
    }
  });

});

window.onhashchange = function () {
  if (window.innerDocClick) {
    //Your own in-page mechanism triggered the hash change
  } else {
    //Browser back or forward button was pressed
  }
};

Dies funktioniert für Chrome und IE und nicht für FireFox. Ich arbeite immer noch daran, FireFox richtig zu machen. Jede einfache Möglichkeit, das Klicken des Browsers vorwärts/rückwärts zu erkennen, ist willkommen, nicht besonders in JQuery, sondern auch in AngularJS oder einfachem Javascript. 

1
Dhruv Gupta
if (window.performance && window.performance.navigation.type == window.performance.navigation.TYPE_BACK_FORWARD) {
  alert('hello world');
}

Dies ist die einzige Lösung, die für mich funktioniert hat (es handelt sich nicht um eine Onpage-Website). Es funktioniert mit Chrome, Firefox und Safari.

0
escanxr

Ich löste es, indem ich das ursprüngliche Ereignis nachverfolgte, das die hashchange ausgelöst hat (sei es ein Wisch, ein Klick oder ein Rad), so dass das Ereignis nicht mit einer einfachen Landing-on-Page verwechselt werden konnte, und ein zusätzliches Flag verwendet wurde in jeder meiner Event-Bindungen. Der Browser setzt das Flag nicht erneut auf false, wenn Sie auf die Schaltfläche "Zurück" klicken:

var evt = null,
canGoBackToThePast = true;

$('#next-slide').on('click touch', function(e) {
    evt = e;
    canGobackToThePast = false;
    // your logic (remember to set the 'canGoBackToThePast' flag back to 'true' at the end of it)
}
0
user1025495
 <input style="display:none" id="__pageLoaded" value=""/>


 $(document).ready(function () {
        if ($("#__pageLoaded").val() != 1) {

            $("#__pageLoaded").val(1);


        } else {
            shared.isBackLoad = true;
            $("#__pageLoaded").val(1);  

            // Call any function that handles your back event

        }
    });

Der obige Code hat für mich funktioniert. Wenn der Benutzer bei mobilen Browsern auf die Schaltfläche "Zurück" klickte, wollten wir den Seitenstatus gemäß seinem vorherigen Besuch wiederherstellen.

0
Ashwin

Dies wird auf jeden Fall funktionieren

$(window).on('popstate', function(event) {
 alert("pop");
});
0
rohan parab

Sieh dir das an:

history.pushState(null, null, location.href);
    window.onpopstate = function () {
        history.go(1);
    };

es funktioniert gut...

0
Jorge Rocha