Czy możesz używać nawigacji hash bez wpływu na historię?

100

Obawiam się, że może to być niemożliwe, ale czy istnieje sposób na zmianę wartości skrótu adresu URL bez pozostawiania wpisu w historii przeglądarki i bez ponownego ładowania ? Albo zrobić odpowiednik?

Jeśli chodzi o szczegóły, opracowałem podstawową nawigację z hashami w następujący sposób:

//hash nav -- works with js-tabs
var getHash = window.location.hash;
var hashPref = "tab-";
function useHash(newHash) {
    //set js-tab according to hash
    newHash = newHash.replace('#'+hashPref, '');
    $("#tabs li a[href='"+ newHash +"']").click();
}
function setHash(newHash) {
    //set hash according to js-tab
    window.location.hash = hashPref + newHash;

    //THIS IS WHERE I would like to REPLACE the location.hash
    //without a history entry

}
    // ... a lot of irrelavent tabs js and then....

    //make tabs work
    $("#tabs.js-tabs a").live("click", function() {
        var showMe = $(this).attr("href");
        $(showMe).show();
        setHash(showMe);
        return false;
    });
    //hash nav on ready .. if hash exists, execute
    if ( getHash ){
        useHash(getHash);
    }

Oczywiście przy użyciu jQuery. Chodzi o to, że w tym konkretnym przypadku 1) zmuszanie użytkownika do powrotu do każdej zmiany karty może skutecznie `` złamać przycisk Wstecz '' poprzez gromadzenie niepotrzebnych odwołań, i 2) nie zachowywanie karty, na której jest obecnie, po naciśnięciu przycisku odświeżania irytacja.


źródło
Dlaczego chcesz zmienić hash, jeśli nie chcesz śledzić historii? : |
Ionuț Staicu
10
Ponieważ przy odświeżaniu najlepiej byłoby pokazać użytkownikowi kartę, na której był, ale ponieważ mogą oni przewijać się między kartami, niepotrzebnie zapełniłby ich historię wpisami, przez co przycisk Wstecz byłby faktycznie mniej przydatny. To jest tylko przykład - może to dotyczyć dowolnego momentu, w którym musisz zapisać stan tymczasowy, ale nie chcesz polegać na plikach cookie ani wypełniać nimi pliku tymczasowego użytkownika. Po odświeżeniu zawartość js jest taka, jak ją zostawiłeś - nie opuściłeś strony i nie jest to punkt przejścia ani strona pseudo, więc wpis historii może zakłócać tylko standardową nawigację.

Odpowiedzi:

95

location.replace("#hash_value_here");działało dobrze, dopóki nie odkryłem, że nie działa na IOS Chrome. W takim przypadku użyj:

history.replaceState(undefined, undefined, "#hash_value")

history.replaceState () działa dokładnie tak samo, jak history.pushState () z tym wyjątkiem, że replaceState () modyfikuje bieżący wpis historii zamiast tworzyć nowy.

Pamiętaj, aby zachować #lub ostatnia część adresu URL zostanie zmieniona.

Lucia
źródło
3
Całkowicie droga dla nowoczesnych przeglądarek; należy jednak pamiętać o częściowym wsparciu zarządzania historią sesji.
Matt
Nie mam pojęcia, jak tego używać. Czy powinienem nadal używać, window.location.hash = 'my-hash';a następnie history.replaceState(undefined, undefined, "#my-hash")?
Bram Vanroy
2
@BramVanroy Nie, wystarczy użyć tego ostatniego.
Lucia
2
O ile nie używasz: selektorów docelowych ... wtedy funkcje historii są bezużyteczne, ponieważ ta część specyfikacji (interakcja css z operacjami historii) wydaje się nie być obecnie zdefiniowana, a styl nie jest ponownie obliczany przy zastępowaniu historii przez większość / wszystkie przeglądarki.
morphles
@Luxiyalu, czym się history.replaceStateróżni od location.replace?
Pacerier
99
location.replace("#hash_value_here"); 

Wydaje się, że powyższe robi to, czego szukasz.

Matt
źródło
4
To jest to. A jeśli masz segmenty uri, location.replace (window.location + "#hash") zachowa je.
przetrząsacze
7
Oddelegowanie tej metody, znacznie czystsze, żałuję, że nie została oznaczona jako poprawna odpowiedź.
joeellis
14
window.location.replace(('' + window.location).split('#')[0] + '#' + hash);aby po prostu zaktualizować skrót
johnstorm
1
Testuję to w Chrome 30 pod Windows 8, jeśli przejdę do Historii Chrome i wybiorę „Więcej z tej witryny” pod moim testowym adresem URL, zobaczę wszystkie skróty, które zostały dodane tą metodą.
Alex Vang
1
Uważaj na to, że location.replace ('# hash_value_here') zmienia tylko fragment z krzyżykiem, a nie ścieżkę, więc nie powoduje ładowania strony ... Z wyjątkiem sytuacji, gdy dokument zawiera znacznik podstawowy: <base href ="http://example.com/" /> Jeśli zawiera znacznik podstawowy , wtedy kiedy użyjesz metody replace tylko z początkiem "#hash_value_here", w rzeczywistości będzie to tak, jakbyś powiedział `location.replace (' example.com/#hash_value_here' ). Wydaje się to oczywiste, gdy czytasz to tutaj, ale jest to problem, gdy jesteś na stronie z fragmentem ścieżki i nie zdajesz sobie sprawy, że podstawa jest ustawiona.
Tyler Kasten
6

Edycja: minęło już kilka lat, a przeglądarki ewoluowały.

@ Luxiyalu za odpowiedź jest droga

- Stara odpowiedź -

Ja też uważam, że to niemożliwe (w tej chwili). Ale dlaczego musisz zmieniać wartość skrótu, jeśli nie zamierzasz jej używać?

Uważam, że głównym powodem, dla którego jako programiści używamy wartości skrótu, jest umożliwienie użytkownikowi dodania zakładek do naszych stron lub zapisanie stanu w historii przeglądarki. Jeśli nie chcesz tego robić, po prostu zapisz stan w zmiennej i zacznij od tego.

Myślę, że powodem używania hasha jest praca z wartością, która jest poza naszą kontrolą. Jeśli jej nie potrzebujesz, prawdopodobnie oznacza to, że masz wszystko pod kontrolą, więc po prostu zapisz stan w zmiennej i pracuj z nią. (Lubię się powtarzać)

Mam nadzieję, że to ci pomoże. Może jest łatwiejsze rozwiązanie twojego problemu.

UPDATE: Co powiesz na to:

  1. Skonfiguruj pierwszy hash i upewnij się, że zostanie zapisany w historii przeglądarki.
  2. Gdy zostanie wybrana nowa karta, zrób to window.history.back(1), co spowoduje, że historia wróci z pierwszego skrótu init.
  3. Teraz ustawiasz nowy hash, dlatego tabulacja spowoduje tylko jeden wpis w historii.

Prawdopodobnie będziesz musiał użyć kilku flag, aby wiedzieć, czy bieżący wpis można „usunąć”, cofając się, czy po prostu pominiesz pierwszy krok. I aby upewnić się, że twoja metoda ładowania "hasha" nie zostanie wykonana, gdy wymusisz rozszerzenie history.back.

guzart
źródło
Jest bardzo możliwe, że brakuje mi czegoś podstawowego (wyczerpanie to miła wymówka, pójdę z tym), ale czy mówisz, że mogę ustawić zmienną, która zachowa zmienioną wartość po przeładowaniu? Poza tym z ciasteczkiem? (Jakoś ciasteczka wydają się przesadzone ...) Może to nie było jasne. Będę używał wartości skrótu - szczególnie podczas ponownego ładowania. Dziękuję za odpowiedź!
Aby wyjaśnić moje wyjaśnienie: jeśli użytkownik trafi ponownie załaduj. Po to jest haszysz. Nadal staram się unikać ponownego ładowania podczas ich normalnego użytkowania (zmiana / klikanie kart).
Ok, więc po przeładowaniu będziesz używać niektórych wartości dla informacji. Niestety, wartość skrótu zostanie wybrana przez historię niektórych przeglądarek. Przykro mi to mówić, ale z mojego doświadczenia, ciasteczka są najlepszym rozwiązaniem. Jeśli chcesz czegoś, czego historia przeglądarki nie wykrywa, ale aby zachować po przeładowaniu, niestety pliki cookie. Jeśli użytkownik klikał odsyłacz, możesz ustawić odsyłacz jako query ( ?mystate=greatness), nawet jeśli nie musi to być ajax, możesz zapisać informacje do odczytania przez javascript podczas inicjowania żądania.
guzart
Tak, hash służy do zapisywania informacji o użytkowniku po wciśnięciu przeładowania, ale problem w Twojej sytuacji jest taki, że niektóre przeglądarki zapisują te zmiany w historii, tak po prostu działają ... :(
guzart
Tak, myślę, że masz rację. Ach tak. (Chciałbym udowodnić, że się mylisz jakąś inną metodą lub czymś.)
-1

Zawsze możesz utworzyć detektor zdarzeń, który będzie przechwytywał zdarzenia kliknięcia w hiperłączu, aw funkcji wywołania zwrotnego umieść e.preventDefault (), co powinno uniemożliwić przeglądarce wstawienie go do historii.

Ayman Farhat
źródło