Пример history.replaceState ()?


127

Может ли кто-нибудь привести рабочий пример для history.replaceState? Вот что говорит w3.org :

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

Обновляет текущую запись в истории сеанса, чтобы она содержала указанные данные, заголовок и, если он указан, а не null, URL.

Обновить:

Это отлично работает:

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

URL меняется, но заголовок не меняется. Это ошибка или я что-то упускаю? Проверено на последней версии Chrome.


3
Обычно я не добавляю дополнительные библиотеки для вопросов по JavaScript, но в этом случае сделаю исключение. Библиотека History.js - это небольшая прокладка, которая устраняет множество причудливых проступков в History API в современных браузерах. Он даже обеспечивает дополнительную поддержку старых версий IE.
Pointy

2
У MDN довольно хорошая рецензия на Манипулирование историей браузера
Саклин

@Pointy history.js отлично работает. Я обновил код в своем вопросе. Нет, моя проблема в том, что я не могу вернуться на предыдущую страницу с помощью кнопки возврата в браузере
Сержас

3
Согласно Mozilla , этот titleпараметр фактически не используется.
Rocket Hazmat

3
Первый ответ на самом деле не должен быть принятым ответом, учитывая, что вопрос задает replaceStateпример, а принятый ответ никоим образом не является replaceStateпримером.
CorayThan 05

Ответы:


68

На самом деле это ошибка, но уже 2 года преднамеренная. Проблема заключается в некоторых неясных спецификациях и сложности, когда document.titleзадействованы и назад / вперед.

См. Справку об ошибках в Webkit и Mozilla . Также Opera при внедрении History API заявила, что не использует параметр title и, вероятно, до сих пор не использует.

В настоящее время второй аргумент pushState и replaceState - заголовок записи в истории - не используется в реализации Opera, но может быть одним днем.

Возможное решение

Единственный способ, который я вижу, - это изменить элемент заголовка и вместо этого использовать pushState:

document.getElementsByTagName('title')[0].innerHTML = 'bar';
window.history.pushState( {} , 'bar', '/bar' );

Для пользователей jquery: попробуйте $ ("title"). Html (_title);
сурадж джайн

3
это может привести к тому, что пользователям потребуется «дважды щелкнуть» кнопку возврата в зависимости от того, как вы это реализуете. Более простым решением может быть использование replaceState()и простая установка заголовка документа вручнуюdocument.title = "title"
newshorts

38

Вот минимальный надуманный пример.

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

Это еще не все, replaceState()но я не знаю, что именно вы хотите с этим делать.


2
URL-адрес меняется, но заголовок не меняется .. протестировано с последним Chrome @trott
Serjas

6
@Serjas titleПараметр in replaceState(), насколько мне известно, игнорируется во всех браузерах.
Тротт

10

history.pushStateпомещает текущее состояние страницы в стек истории и изменяет URL-адрес в адресной строке. Итак, когда вы вернетесь, это состояние (объект, который вы передали) будет возвращен вам.

В настоящее время это все, что он делает. Любые другие действия на странице, такие как отображение новой страницы или изменение заголовка страницы, должны выполняться вами.

Спецификация W3C, на которую вы ссылаетесь, является всего лишь черновиком, и браузер может реализовать ее по-другому. Например, Firefoxtitle полностью игнорирует параметр.

Вот простой пример, pushStateкоторый я использую на своем веб-сайте.

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

29
Почему в принятом ответе объясняется «pushState» вместо «replaceState»?
Giwrgos Tsopanoglou

1
@GiwrgosTsopanoglou: Я ответил на это год назад, поэтому я не уверен, почему :-P В любом случае replaceStateменяет текущее состояние страницы. Он позволяет вам изменить объект состояния и URL-адрес текущего состояния страницы.
Rocket Hazmat

2
Просто странно, что я искал информацию о replaceState и в итоге прочитал о pushState: P
Giwrgos Tsopanoglou

6

посмотрите на пример

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

и поиск location.hash;


2

Второй аргумент Заголовок не означает заголовок страницы - это скорее определение / информация о состоянии этой страницы.

Но мы все еще можем изменить заголовок с помощью события onpopstate и передать имя заголовка не из второго аргумента, а как атрибут из первого параметра, переданного как объект

Ссылка: http://spoiledmilk.com/blog/html5-changing-the-browser-url-without-refreshing-page/


2

Согласно документу истории MDN.
Здесь ясно сказано, что второй аргумент на будущее используется, а не сейчас. Вы правы, что второй аргумент касается заголовка веб-страницы, но в настоящее время он игнорируется всеми основными браузерами.

Firefox в настоящее время игнорирует этот параметр, хотя может использовать его в будущем. Передача здесь пустой строки должна быть защищена от будущих изменений метода. Как вариант, вы можете передать краткое название состояния, в которое вы переходите.


Второй аргумент вовсе не относится к заголовку веб-страница - MDN документ , который вы связаны говорит «передать короткое название для государства , к которому ты двигаешься.» , Это согласуется с документацией по интерфейсу истории W3C, в которой говорится: «Помещает данные в историю сеанса с заданным заголовком» . Данные в этой фразе - это данные о состоянии , поэтому снова заголовок относится к состоянию (данным).
Стивен П.

1

Я очень хотел ответить на ответ @Sev.

Сев прав, внутри ошибка window.history.replaceState

Чтобы исправить это, просто перепишите конструктор, задав заголовок вручную.

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

2
Не делай этого. Перезапись функций по умолчанию - действительно плохой стиль
Рене Рот

3
что еще вы посоветуете, если вам нужно исправить эту ошибку?
Glenn Plas

@GlennPlas открывает пиар против
репозитория Repo

0

Предположим, https://www.mozilla.org/foo.html выполняет следующий код JavaScript:

const stateObj = { foo: 'bar' };

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

В результате в строке URL отобразится https://www.mozilla.org/bar2.html , но браузер не загрузит bar2.html или даже не проверит, существует ли bar2.html.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.