On - window.location.hash - Zmienić?

558

Używam Ajax i skrótu do nawigacji.

Czy istnieje sposób, aby sprawdzić, czy tak się window.location.hashzmieniło?

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

Działa, jeśli sprawdzę to podczas ładowania dokumentu.

Ale jeśli mam nawigację opartą na #hash, to nie działa po naciśnięciu przycisku Wstecz w przeglądarce (więc skaczę z bla # 456 do bla # 123).

Pokazuje się w polu adresu, ale nie mogę go złapać za pomocą JavaScript.

MilMike
źródło
6
Sprawdź
Xavi
9
History.js obsługuje funkcję zarządzania stanem HTML5 (więc nie musisz już używać skrótów!) I z wdziękiem degraduje ją do przeglądarek HTML4 za pomocą skrótów. Obsługuje jQuery, MooTools i Prototyp po wyjęciu z pudełka.
balupton 30.01.11
@balupton, W rzeczywistości nadal musimy używać skrótów, aby przekazać użytkownikowi informację zwrotną, że „nowa strona” została wstawiona do jego historii, chyba że użyjesz zmiany adresu URL jako opinii.
Pacerier
1
[Hasher] github.com/millermedeiros/hasher
Vishnoo Rath
hmm ... Myślę, że potrzebujesz moar jQuery
RaisingAgent

Odpowiedzi:

617

Jedynym sposobem, aby to naprawdę zrobić (i to, w jaki sposób robi to „reallysimplehistory”), jest ustawienie interwału, który sprawdza bieżący skrót i porównanie go z tym, co było wcześniej, robimy to i pozwalamy subskrybentom subskrybować zmienione zdarzenie, które uruchamiamy, jeśli skrót się zmieni ... nie jest idealny, ale przeglądarki naprawdę nie obsługują tego zdarzenia natywnie.


Zaktualizuj, aby zachować aktualność tej odpowiedzi:

Jeśli używasz jQuery (która dziś powinna być w pewnym stopniu fundamentalna), dobrym rozwiązaniem jest użycie abstrakcji, którą daje ci jQuery, używając systemu zdarzeń do nasłuchiwania zdarzeń hashchange na obiekcie okna.

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

Fajną rzeczą jest to, że możesz pisać kod, który nie musi się nawet martwić o obsługę hashchange, jednak musisz zrobić trochę magii, w postaci nieco mniej znanej specjalnej funkcji jQuery jQuery .

Dzięki tej funkcji zasadniczo można uruchomić kod instalacyjny dla dowolnego zdarzenia, za pierwszym razem, gdy ktoś próbuje użyć zdarzenia w jakikolwiek sposób (np. Powiązanie ze zdarzeniem).

W tym kodzie instalacyjnym możesz sprawdzić, czy natywna obsługa przeglądarki jest obsługiwana, a jeśli przeglądarka natywnie tego nie implementuje, możesz skonfigurować pojedynczy licznik czasu, aby sondować zmiany i wyzwalać zdarzenie jQuery.

To całkowicie odsuwa twój kod od konieczności zrozumienia tego problemu wsparcia, implementacja tego rodzaju specjalnego zdarzenia jest trywialna (aby uzyskać prostą 98% działającą wersję), ale po co to robić, skoro ktoś już to zrobił .

meandmycode
źródło
7
IE8 robi. Więcej w przyszłości
Sergey Ilinsky
28
Najnowsza wersja Firefoksa (3.6 alpha) obsługuje teraz także natywne wydarzenie zmienione hash: developer.mozilla.org/en/DOM/window.onhashchange Z pewnością warto sprawdzić to wydarzenie, ale pamiętaj, że IE8 poinformuje Cię o zdarzeniu istnieje, gdy jest uruchomiony w trybie zgodnym z IE7 .. niestety zdarzenie się nie uruchamia .. musisz sprawdzić, czy to zdarzenie i czy przeglądarka nie wydaje się być IE7 .. westchnienie (lub próba uruchomienia zdarzenia metodą IE fireEvent).
meandmycode
8
W chwili pisania tego tekstu WebKit uruchamia również hashchangezdarzenie, podczas gdy Safari (stabilny) jeszcze nie.
jholster
51
Aby dodać kolejną aktualizację, hashchangewydarzenie jest teraz szeroko obsługiwane: caniuse.com/#search=hash
Paystey
19
Czy jestem jedynym, który uważa, że ​​niezamówione odpowiedzi jQuery są uciążliwe?
Luc
290

HTML5 określa hashchangezdarzenie . To wydarzenie jest teraz obsługiwane przez wszystkie nowoczesne przeglądarki . Obsługa została dodana w następujących wersjach przeglądarki:

  • Internet Explorer 8
  • Firefox 3.6
  • Chrome 5
  • Safari 5
  • Opera 10.6
Miles
źródło
20
Aktualizacja: FF 5, Safari 5 i Chrome 12 obsługują to wydarzenie od czerwca 2011 r.
james.garriss
2
Oto strona CanIUse dla hashchange . Oto hashchange na quirksmode . Obsługa IE jest błędna w odniesieniu do rozróżniania wielkości liter.
Tobu,
3
@ wszyscy, nie trzeba ciągle dołączać do odpowiedzi w sekcji komentarzy - po to służy przycisk „Edytuj”. :)
Michael Martin-Smucker
15
użycie:window.onhashchange = function() { doYourStuff(); }
Chris
4
Dokumentacja MDN zdarzenia hashchange .
Dabowheel
52

Zauważ, że w przypadku Internet Explorera 7 i Internet Explorera 9 ifpodana będzie prawda (dla „onhashchange” w systemie Windows), ale window.onhashchangenigdy się nie uruchomi, więc lepiej przechowywać hash i sprawdzać go po każdych 100 milisekundach, czy jest zmieniony czy nie dla wszystkich wersji Internet Explorera.

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

EDYCJA - od wersji jQuery 1.9 $.browser.msienie jest obsługiwana. Źródło: http://api.jquery.com/jquery.browser/

Khan Salahuddin
źródło
14

W przeglądarkach IE jest wiele sztuczek związanych z History i window.location.hash:

  • Zgodnie z pierwotnym pytaniem, jeśli przejdziesz ze strony a.html # b do a.html # c, a następnie naciśniesz przycisk Wstecz, przeglądarka nie wie, że ta strona się zmieniła. Powiem to na przykładzie: window.location.href będzie „a.html # c”, bez względu na to, czy jesteś w a.html # b czy a.html # c.

  • W rzeczywistości a.html # bi a.html # c są przechowywane w historii tylko wtedy, gdy elementy „<a name="#b">” i „<a name="#c">” istniały wcześniej na stronie.

  • Jeśli jednak umieścisz ramkę iframe na stronie, przejdź od a.html # b do a.html # c w tej ramce iframe, a następnie naciśnij przycisk Wstecz, iframe.contentWindow.document.location.href zmienia się zgodnie z oczekiwaniami.

  • Jeśli użyjesz „document.domain = coś ” w kodzie, nie będziesz mieć dostępu do iframe.contentWindow.document.open () ”(i robi to wielu menedżerów historii)

Wiem, że to nie jest prawdziwa odpowiedź, ale może notatki historii IE są dla kogoś przydatne.

Sergio Cinos
źródło
11

Ben Alman ma świetną wtyczkę jQuery do radzenia sobie z tym: http://benalman.com/projects/jquery-hashchange-plugin/

Jeśli nie używasz jQuery, może to być interesujące odniesienie do analizy.

CJ
źródło
Wtyczka Ben Alman wydaje się nie być już utrzymywana. Istnieje jednak wiele widelców.
Mnebuerquo,
9

Możesz łatwo wdrożyć obserwatora (metodę „watch”) we właściwości „hash” obiektu „window.location”.

Firefox ma własną implementację do obserwowania zmian obiektu , ale jeśli używasz innej implementacji (takiej jak Obserwuj właściwości obiektu w JavaScript ) - w przypadku innych przeglądarek to załatwi sprawę.

Kod będzie wyglądał następująco:

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

Następnie możesz to przetestować:

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

I oczywiście uruchomi to funkcję obserwatora.

gion_13
źródło
Lepsze użycie: window.location.href zamiast window.location.
Codebeat
3
Ogląda okno. Lokalizacja. Skrót, a nie okno. Lokalizacja.
niezdefiniowany
1
@BrianMortenson: zgodnie z dokumentacją ( developer.mozilla.org/en-US/docs/JavaScript/Reference/... ) musisz zastosować watchobiekt, który jest właścicielem zmieniającej się właściwości i chcesz ją obserwować.
gion_13,
@ gion_13 Tak, właśnie to chciałem wskazać. Przez „On” miałem na myśli ciebie, i to było skierowane na komentarz Erwinusa. Powinienem być bardziej dokładny. Dziękujemy za wyjaśnienie.
niezdefiniowany
7

Używałem tego w aplikacji reagującej, aby URL wyświetlał różne parametry w zależności od widoku, na którym był użytkownik.

Oglądałem parametr skrótu za pomocą

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

Następnie

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

Działał smakołyk, działa z przyciskami przeglądarki do przodu i do tyłu, a także w historii przeglądarki.

Sprose
źródło
1
w swoim addEventListenerpołączeniu powinieneś usunąć ()zdoSomethingWithChangeFunction
Jason S
Czy możesz podać powód usunięcia ()? Wiem, że będzie działał z jednym z nich, a mniej kodu to w większości lepsza opcja, ale wydaje się to wybredne, chyba że istnieje istotny powód, aby to zrobić?
Sprose
6
? to nie powinno działać (). addEventListenerFunkcja wymaga, aby przejść w funkcji. doSomethingWithChangeFunctionjest funkcją. doSomethingWithChangeFunction()jest wartością zwracaną przez tę funkcję, która w tym przypadku nie jest funkcją.
Jason S
6

Przyzwoite wdrożenie można znaleźć na stronie http://code.google.com/p/reallysimplehistory/ . Jedynym (ale także) problemem i błędem jest: w Internet Explorerze modyfikacja skrótu lokalizacji ręcznie zresetuje cały stos historii (jest to problem przeglądarki i nie można go rozwiązać).

Uwaga: Internet Explorer 8 obsługuje zdarzenie „hashchange”, a ponieważ staje się częścią HTML5, możesz spodziewać się, że inne przeglądarki nadrobią zaległości.

Siergiej Iliński
źródło
1

Inną świetną implementacją jest jQuery History, która wykorzysta natywne zdarzenie onhashchange, jeśli jest obsługiwane przez przeglądarkę, jeśli nie, użyje odpowiednio elementu iframe lub interwału dla przeglądarki, aby zapewnić pomyślną emulację wszystkich oczekiwanych funkcji. Zapewnia również przyjemny interfejs do łączenia się z niektórymi stanami.

Kolejnym projektem wartym odnotowania jest także jQuery Ajaxy, który jest prawie rozszerzeniem historii jQuery, aby dodać ajax do miksu. Kiedy zaczynasz używać ajax z hashami, staje się to dość skomplikowane !

balupton
źródło
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);

To wszystko ... teraz, za każdym razem, gdy naciśniesz przycisk Wstecz lub Dalej, strona zostanie ponownie załadowana zgodnie z nową wartością skrótu.

ordynans
źródło
nie używaj ciągów
ewaluacyjnych
1

Używam path.js do routingu po stronie klienta. Uważam, że jest dość zwięzły i lekki (został również opublikowany w NPM) i korzysta z nawigacji opartej na haszowaniu.

path.js NPM

path.js GitHub

Tomek
źródło
0

Użyłem wtyczki jQuery, HUtil , i napisałem na niej interfejs podobny do historii YUI .

Sprawdź to raz. Jeśli potrzebujesz pomocy, mogę pomóc.

moha297
źródło