On - window.location.hash - Ändern?

558

Ich benutze Ajax und Hash für die Navigation.

Gibt es eine Möglichkeit zu überprüfen, ob sich das so window.location.hashgeändert hat?

http://example.com/blah # 123 bis http://example.com/blah # 456

Es funktioniert, wenn ich es beim Laden des Dokuments überprüfe.

Aber wenn ich eine # Hash-basierte Navigation habe, funktioniert dies nicht, wenn ich die Zurück-Taste im Browser drücke (also springe ich von bla # 456 zu bla # 123).

Es wird im Adressfeld angezeigt, aber ich kann es mit JavaScript nicht abfangen.

MilMike
quelle
6
Kasse dieses jquery Plugin: github.com/cowboy/jquery-hashchange
Xavi
9
History.js unterstützt die HTML5-Statusverwaltungsfunktion (Sie müssen also keine Hashes mehr verwenden!) Und verschlechtert sie mithilfe von Hash-Änderungen ordnungsgemäß in HTML4-Browser. Es unterstützt sofort jQuery, MooTools und Prototype.
Balupton
@balupton, Eigentlich müssen wir noch Hashes verwenden , um dem Benutzer Feedback zu geben, dass eine "neue Seite" in seinen Verlauf eingefügt wurde, es sei denn, Sie verwenden das Ändern von URLs als Feedback.
Pacerier
1
[Hasher] github.com/millermedeiros/hasher
Vishnoo Rath
hmm ... ich denke du brauchst moar jQuery
RaisingAgent

Antworten:

617

Der einzige Weg, dies wirklich zu tun (und so macht es die 'wirklich einfache Geschichte'), besteht darin, ein Intervall festzulegen, in dem der aktuelle Hash ständig überprüft und mit dem vorherigen verglichen wird. Wir tun dies und lassen Abonnenten eine Änderung abonnieren Ereignis, das wir auslösen, wenn sich der Hash ändert. Es ist nicht perfekt, aber Browser unterstützen dieses Ereignis nicht nativ.


Update, um diese Antwort aktuell zu halten:

Wenn Sie jQuery verwenden (was heute für die meisten etwas grundlegend sein sollte), besteht eine gute Lösung darin, die Abstraktion zu verwenden, die jQuery Ihnen bietet, indem Sie das Ereignissystem verwenden, um Hashchange-Ereignisse auf dem Fensterobjekt abzuhören.

$(window).on('hashchange', function() {
  //.. work ..
});

Das Schöne hier ist, dass Sie Code schreiben können, der sich nicht einmal um die Unterstützung von Hashchange kümmern muss. Sie müssen jedoch etwas Magie in Form einer etwas weniger bekannten jQuery-Funktion jQuery-Sonderereignisse ausführen .

Mit dieser Funktion können Sie im Wesentlichen Setup-Code für jedes Ereignis ausführen, wenn jemand zum ersten Mal versucht, das Ereignis auf irgendeine Weise zu verwenden (z. B. durch Bindung an das Ereignis).

In diesem Setup-Code können Sie nach nativer Browserunterstützung suchen. Wenn der Browser dies nicht nativ implementiert, können Sie einen einzelnen Timer einrichten, um nach Änderungen zu suchen und das jQuery-Ereignis auszulösen.

Das komplett entbindet Code aus , um diese Unterstützung Problem zu verstehen, die Durchführung einer besonderen Aktion Veranstaltung dieser Art trivial ist (eine einfache 98% Arbeitsversion zu bekommen), aber warum tun, wenn jemand anderes bereits hat .

meandmycode
quelle
7
IE8 tut. Weitere werden
folgen
28
Der neueste Firefox-Build (3.6 Alpha) unterstützt jetzt auch das native Hash-Änderungsereignis: developer.mozilla.org/en/DOM/window.onhashchange Es lohnt sich auf jeden Fall, dieses Ereignis zu überprüfen. Beachten Sie jedoch, dass IE8 Ihnen das Ereignis mitteilt existiert, wenn es im IE7-Kompatibilitätsmodus ausgeführt wird. Leider wird das Ereignis nicht ausgelöst. Sie müssen nach dem Ereignis suchen und feststellen, dass der Browser nicht IE7 zu sein scheint. Seufzen (oder versuchen, das Ereignis auszulösen mit der fireEvent-Methode des IE).
Meandmycode
8
Zum Zeitpunkt des Schreibens hashchangelöst WebKit auch ein Ereignis aus, während Safari (stabil) dies noch nicht tut.
Jholster
51
Um noch ein weiteres Update hinzuzufügen, wird die hashchangeVeranstaltung jetzt weitgehend unterstützt: caniuse.com/#search=hash
Paystey
19
Bin ich der einzige, der glaubt, dass unaufgeforderte jQuery-Antworten ein Schmerz sind?
Luc
290

HTML5 gibt ein hashchangeEreignis an . Dieses Ereignis wird jetzt von allen modernen Browsern unterstützt . Unterstützung wurde in den folgenden Browserversionen hinzugefügt:

  • Internet Explorer 8
  • Firefox 3.6
  • Chrome 5
  • Safari 5
  • Opera 10.6
Meilen
quelle
20
Update: FF 5, Safari 5 und Chrome 12 unterstützen dieses Ereignis ab Juni 2011.
james.garriss
2
Hier ist die CanIUse-Seite für Hashchange . Hier ist Hashchange im Quirksmode . Die IE-Unterstützung ist in Bezug auf die Groß- und Kleinschreibung fehlerhaft.
Tobu
3
@jeder, Sie müssen nicht ständig an die Antwort im Kommentarbereich anhängen - dafür ist die Schaltfläche "Bearbeiten" gedacht. :)
Michael Martin-Smucker
15
Verwendung:window.onhashchange = function() { doYourStuff(); }
Chris
4
MDN-Dokumentation des Hashchange-Ereignisses .
Dabowheel
52

Beachten Sie, dass im Fall von Internet Explorer 7 und Internet Explorer 9 die ifAnweisung true angibt (für "onhashchange" in Windows), aber window.onhashchangeniemals ausgelöst wird. Es ist daher besser, Hash zu speichern und nach jeweils 100 Millisekunden zu überprüfen, ob er geändert wurde oder nicht für alle Versionen von Internet Explorer.

    if (("onhashchange" in window) && !($.browser.msie)) {
         window.onhashchange = function () {
              alert(window.location.hash);
         }
         // Or $(window).bind( 'hashchange',function(e) {
         //       alert(window.location.hash);
         //   });
    }
    else {
        var prevHash = window.location.hash;
        window.setInterval(function () {
           if (window.location.hash != prevHash) {
              prevHash = window.location.hash;
              alert(window.location.hash);
           }
        }, 100);
    }

BEARBEITEN - Da jQuery 1.9 $.browser.msienicht unterstützt wird. Quelle: http://api.jquery.com/jquery.browser/

Khan Salahuddin
quelle
14

Es gibt viele Tricks, um mit Verlauf und window.location.hash in IE-Browsern umzugehen:

  • Wie in der ursprünglichen Frage erwähnt, weiß der Browser nicht, dass sich diese Seite geändert hat, wenn Sie von Seite a.html # b zu a.html # c wechseln und dann auf die Schaltfläche "Zurück" klicken. Lassen Sie es mich mit einem Beispiel sagen: window.location.href ist 'a.html # c', egal ob Sie sich in a.html # b oder a.html # c befinden.

  • Tatsächlich werden a.html # b und a.html # c nur dann im Verlauf gespeichert, wenn die Elemente '<a name="#b">' und '<a name="#c">' zuvor auf der Seite vorhanden sind.

  • Wenn Sie jedoch einen Iframe in eine Seite einfügen, navigieren Sie in diesem Iframe von a.html # b zu a.html # c und klicken Sie dann auf die Schaltfläche "Zurück". Iframe.contentWindow.document.location.href ändert sich wie erwartet.

  • Wenn Sie ‚document.domain = etwas ‘ in Ihrem Code, dann können Sie keinen Zugriff auf iframe.contentWindow.document.open ()‘(und viele History Manager das tut)

Ich weiß, dass dies keine echte Antwort ist, aber vielleicht sind IE-History-Notizen für jemanden nützlich.

Sergio Cinos
quelle
11

Ben Alman hat ein großartiges jQuery-Plugin, um damit umzugehen: http://benalman.com/projects/jquery-hashchange-plugin/

Wenn Sie jQuery nicht verwenden, ist dies möglicherweise eine interessante Referenz zum Präparieren.

CJ.
quelle
Das Ben Alman Plugin scheint nicht mehr gepflegt zu sein. Es gibt jedoch eine Reihe von Gabeln.
Mnebuerquo
9

Sie können problemlos einen Beobachter (die "watch" -Methode) für die "hash" -Eigenschaft des "window.location" -Objekts implementieren.

Firefox verfügt über eine eigene Implementierung zum Überwachen von Objektänderungen . Wenn Sie jedoch eine andere Implementierung verwenden (z. B. Änderungen der Objekteigenschaften in JavaScript überwachen ), reicht dies für andere Browser aus.

Der Code sieht folgendermaßen aus:

window.location.watch(
    'hash',
    function(id,oldVal,newVal){
        console.log("the window's hash value has changed from "+oldval+" to "+newVal);
    }
);

Dann können Sie es testen:

var myHashLink = "home";
window.location = window.location + "#" + myHashLink;

Und das wird natürlich Ihre Beobachterfunktion auslösen.

gion_13
quelle
Besser verwenden: window.location.href anstelle von window.location.
Codebeat
3
Er beobachtet window.location.hash, nicht window.location.
undefiniert
1
@BrianMortenson: Gemäß den Dokumenten ( developer.mozilla.org/en-US/docs/JavaScript/Reference/… ) müssen Sie watchauf das Objekt anwenden , dem die sich ändernde Eigenschaft gehört, und Sie möchten sie beobachten.
gion_13
@ gion_13 Ja, genau darauf wollte ich hinweisen. Mit 'Er' meinte ich dich und es richtete sich an Erwinus 'Kommentar. Ich hätte klarer sein sollen. Vielen Dank für Ihren klarstellenden Kommentar.
undefiniert
7

Ich habe dies in einer Reaktionsanwendung verwendet, damit die URL je nach Ansicht des Benutzers unterschiedliche Parameter anzeigt.

Ich habe den Hash-Parameter mit beobachtet

window.addEventListener('hashchange', doSomethingWithChangeFunction());

Dann

doSomethingWithChangeFunction () { 
    // Get new hash value
    let urlParam = window.location.hash;
    // Do something with new hash value
};

Arbeitete ein Vergnügen, arbeitet mit Vorwärts- und Rückwärts-Browser-Schaltflächen und auch im Browserverlauf.

Sprose
quelle
1
in Ihrem addEventListenerAnruf sollten Sie die ()vondoSomethingWithChangeFunction
Jason S
Können Sie einen Grund für das Entfernen von () angeben? Ich weiß, dass es mit beiden funktionieren wird, und weniger Code ist meistens die bessere Option, aber dies scheint wählerisch zu sein, es sei denn, es gibt einen wesentlichen Grund, dies zu sichern?
Sprose
6
? es sollte nicht funktionieren mit (). Für die addEventListenerFunktion müssen Sie eine Funktion übergeben. doSomethingWithChangeFunctionist eine Funktion. doSomethingWithChangeFunction()ist der Rückgabewert dieser Funktion, die in diesem Fall keine Funktion ist.
Jason S
6

Eine anständige Implementierung finden Sie unter http://code.google.com/p/reallysimplehistory/ . Das einzige (aber auch) Problem und der Fehler besteht darin, dass im Internet Explorer durch manuelles Ändern des Standort-Hashs der gesamte Verlaufsstapel zurückgesetzt wird (dies ist ein Browserproblem und kann nicht behoben werden).

Beachten Sie, dass Internet Explorer 8 das Ereignis "Hashchange" unterstützt. Da es Teil von HTML5 wird, können Sie davon ausgehen, dass andere Browser aufholen.

Sergey Ilinsky
quelle
1

Eine weitere großartige Implementierung ist jQuery History, bei der das native onhashchange-Ereignis verwendet wird, wenn es vom Browser unterstützt wird. Andernfalls wird ein für den Browser geeigneter Iframe oder ein Intervall verwendet, um sicherzustellen, dass alle erwarteten Funktionen erfolgreich emuliert werden. Es bietet auch eine schöne Schnittstelle zum Binden an bestimmte Zustände.

Ein weiteres bemerkenswertes Projekt ist jQuery Ajaxy , eine Erweiterung für jQuery History, um dem Mix Ajax hinzuzufügen. Wie wenn Sie anfangen, Ajax mit Hashes zu verwenden, wird es ziemlich kompliziert !

Balupton
quelle
1
var page_url = 'http://www.yoursite.com/'; // full path leading up to hash;
var current_url_w_hash = page_url + window.location.hash; // now you might have something like: http://www.yoursite.com/#123

function TrackHash() {
    if (document.location != page_url + current_url_w_hash) {
        window.location = document.location;
    }
    return false;
}
var RunTabs = setInterval(TrackHash, 200);

Das war's ... jetzt wird die Seite jedes Mal, wenn Sie auf die Schaltfläche "Zurück" oder "Vorwärts" klicken, gemäß dem neuen Hashwert neu geladen.

Batman
quelle
Verwenden Sie keine
Bewertungszeichenfolgen
1

Ich habe path.js für mein clientseitiges Routing verwendet. Ich habe festgestellt, dass es ziemlich prägnant und leicht ist (es wurde auch für NPM veröffentlicht) und verwendet die Hash-basierte Navigation.

path.js NPM

path.js GitHub

Tom
quelle
0

Ich habe ein jQuery-Plugin, HUtil , verwendet und darüber eine YUI History-ähnliche Oberfläche geschrieben.

Probieren Sie es einmal aus. Wenn Sie Hilfe brauchen, kann ich Ihnen helfen.

moha297
quelle