Przykład history.replaceState ()?

127

Czy ktoś może podać działający przykład dla history.replaceState? Co to jest mówi w3.org :

history . replaceState(data, title [, url ] )

Aktualizuje bieżący wpis w historii sesji, aby zawierał podane dane, tytuł i, jeśli podano, a nie pusty, adres URL.

Aktualizacja:

Działa to doskonale:

history.replaceState( {} , 'foo', '/foo' );

Adres URL się zmienia, ale tytuł się nie zmienia. Czy to błąd, czy coś mi brakuje? Przetestowano w najnowszej wersji Chrome.

Serjas
źródło
3
Generalnie nie wypycham bibliotek dodatków do pytań JavaScript, ale w tym przypadku zrobię wyjątek. History.js biblioteka jest mała podkładka, która sprząta wielu dziwacznych wybryków w całej historii API nowoczesnych przeglądarek. Zapewnia nawet opcjonalną obsługę starszych wersji IE.
Pointy
2
MDN całkiem nieźle pisze o manipulowaniu historią przeglądarki
sachleen
@Pointy history.js działa świetnie. Zaktualizowałem kod w moim pytaniu. Nie, mój problem polega na tym, że nie mogę wrócić do poprzedniej strony za pomocą przycisku Wstecz przeglądarki
Serjas
3
Według Mozilli , titleparametr nie jest faktycznie wykorzystywany.
Rocket Hazmat
3
Pierwsza odpowiedź naprawdę nie powinna być odpowiedzią zaakceptowaną, biorąc pod uwagę, że pytanie dotyczy replaceStateprzykładu, a zaakceptowana odpowiedź w żaden sposób nie jest replaceStateprzykładem.
CorayThan,

Odpowiedzi:

68

Rzeczywiście jest to błąd, chociaż zamierzony od 2 lat. Problem polega na niejasnych specyfikacjach i złożoności, kiedydocument.title są zaangażowane i wstecz / dalej.

Zobacz informacje o błędach w Webkit i Mozilli . Również Opera po wprowadzeniu History API powiedziała, że ​​nie używa parametru tytułu i prawdopodobnie nadal tego nie robi.

Obecnie drugi argument pushState i replaceState - tytuł wpisu historii - nie jest używany w implementacji Opery, ale może to być jeden dzień.

Potencjalne rozwiązanie

Jedynym sposobem, w jaki widzę, jest zmiana elementu tytułu i zamiast tego użycie pushState:

document.getElementsByTagName('title')[0].innerHTML = 'bar';
window.history.pushState( {} , 'bar', '/bar' );
Sev
źródło
Dla użytkowników jquery ... spróbuj $ ("tytuł"). Html (_title);
suraj jain
3
może to spowodować, że użytkownicy będą musieli „dwukrotnie kliknąć” przycisk Wstecz, w zależności od tego, jak to zaimplementujesz. Prostszym rozwiązaniem może być replaceState()document.title = "title"
dalsze
38

Oto minimalny, wymyślony przykład.

console.log( window.location.href );  // whatever your current location href is
window.history.replaceState( {} , 'foo', '/foo' );
console.log( window.location.href );  // oh, hey, it replaced the path with /foo

Jest coś więcej, replaceState()ale nie wiem, co dokładnie chcesz z tym zrobić.

Trott
źródło
2
adres url się zmienia, ale tytuł się nie zmienia ... test z najnowszym chrome @trott
Serjas,
6
@Serjas Zgodnie z moją najlepszą wiedzą titleparametr in replaceState()jest ignorowany we wszystkich przeglądarkach.
Trott
10

history.pushStateumieszcza bieżący stan strony na stosie historii i zmienia adres URL w pasku adresu. Tak więc, kiedy wrócisz, ten stan (przekazany obiekt) zostanie Ci zwrócony.

Obecnie to wszystko, co robi. Wszelkie inne działania na stronie, takie jak wyświetlenie nowej strony lub zmiana tytułu strony, muszą zostać wykonane przez Ciebie.

Specyfikacja W3C, którą łączysz, to tylko wersja robocza, a przeglądarka może implementować ją inaczej. Na przykład Firefox ignoruje rozszerzenietitle całkowicie parametr.

Oto prosty przykład tego pushState, którego używam na mojej stronie internetowej.

(function($){
    // Use AJAX to load the page, and change the title
    function loadPage(sel, p){
        $(sel).load(p + ' #content', function(){
            document.title = $('#pageData').data('title');
        });
    }

    // When a link is clicked, use AJAX to load that page
    // but use pushState to change the URL bar
    $(document).on('click', 'a', function(e){
        e.preventDefault();
        history.pushState({page: this.href}, '', this.href);
        loadPage('#frontPage', this.href);
    });

    // This event is triggered when you visit a page in the history
    // like when yu push the "back" button
    $(window).on('popstate', function(e){
        loadPage('#frontPage', location.pathname);
        console.log(e.originalEvent.state);
    });
}(jQuery));
Rocket Hazmat
źródło
29
Dlaczego zaakceptowana odpowiedź wyjaśnia „pushState” zamiast „replaceState”?
Giwrgos Tsopanoglou
1
@GiwrgosTsopanoglou: Odpowiedziałem na to rok temu, więc nie jestem pewien, dlaczego :-P W każdym razie replaceStatezmienia obecny stan strony. Pozwala zmienić obiekt stanu i adres URL bieżącego stanu strony.
Rocket Hazmat
2
To było po prostu dziwne, że szukałem informacji o replaceState i skończyło się na tym, że przeczytałem o pushState: P
Giwrgos Tsopanoglou
6

Spójrz na przykład

window.history.replaceState({
    foo: 'bar'
}, 'Nice URL Title', '/nice_url');

window.onpopstate = function (e) {
    if (typeof e.state == "object" && e.state.foo == "bar") {
        alert("Blah blah blah");
    }
};

window.history.go(-1);

i szukaj location.hash;

avalkab
źródło
2

Według MDN History doc
Jest wyraźnie powiedziane, że drugi argument dotyczący przyszłości nie jest używany na razie. Masz rację, drugi argument dotyczy tytułu strony internetowej, ale obecnie jest on ignorowany przez wszystkie główne przeglądarki.

Firefox obecnie ignoruje ten parametr, chociaż może go używać w przyszłości. Podanie w tym miejscu pustego ciągu powinno być zabezpieczone przed przyszłymi zmianami metody. Alternatywnie możesz podać krótki tytuł dla stanu, do którego się przenosisz.

Munir Khakhi
źródło
Drugi argument jest nie znajdują się w tytule strony internetowej - doc MDN które połączone mówi „przejść krótki tytuł dla państwa , do którego jesteś ruchomej”. . Jest to zgodne z dokumentacją interfejsu historii W3C , która mówi: „Wypycha podane dane do historii sesji o podanym tytule” . Dane w tej frazie to dane o stanie , więc ponownie tytuł odnosi się do stanu (danych).
Stephen P,
1

Naprawdę chciałem odpowiedzieć na odpowiedź @ Seva.

Sev ma rację, jest błąd w pliku window.history.replaceState

Aby to naprawić, po prostu przepisz konstruktora, aby ręcznie ustawić tytuł.

var replaceState_tmp = window.history.replaceState.constructor;
window.history.replaceState.constructor = function(obj, title, url){
    var title_ = document.getElementsByTagName('title')[0];
    if(title_ != undefined){
        title_.innerHTML = title;
    }else{
        var title__ = document.createElement('title');
        title__.innerHTML = title;
        var head_ = document.getElementsByTagName('head')[0];
        if(head_ != undefined){
            head_.appendChild(title__);
        }else{
            var head__ = document.createElement('head');
            document.documentElement.appendChild(head__);
            head__.appendChild(title__);
        }
    }
    replaceState_tmp(obj,title, url);
}
ZACHWYCAJĄCE
źródło
2
Nie rób tego. Nadpisywanie domyślnych funkcji jest naprawdę złym stylem
René Roth
3
co jeszcze sugerujesz, gdy chcesz naprawić ten błąd?
Glenn Plas
@GlennPlas otwiera PR przeciwko repozytorium reakcji :)
zero_cool
0

Załóżmy, że https://www.mozilla.org/foo.html wykonuje następujący JavaScript:

const stateObj = { foo: 'bar' };

history.pushState(stateObj, '', 'bar.html');

Spowoduje to, że pasek adresu URL wyświetli https://www.mozilla.org/bar2.html , ale nie spowoduje załadowania przeglądarki bar2.html ani nawet sprawdzenia, czy bar2.html istnieje.

popielaty
źródło