Приклад history.replaceState ()?


127

Чи може хтось надати робочий приклад для history.replaceState? Про це говорить w3.org :

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

Оновлення поточного запису в історії сеансу, щоб мати дані, назву та, якщо вони надані, а не нульові, URL-адресу.

Оновлення:

Це прекрасно працює:

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

URL змінюється, але назва не змінюється. Це помилка чи я щось пропускаю? Тестовано на останньому Chrome.


3
Як правило, я не натискаю додаткові бібліотеки для питань JavaScript, але в цьому випадку я зроблю виняток. Бібліотека History.js - це невелика примха, яка очищує багато химерних недоброзичливих дій в API API у сучасних браузерах. Він навіть надає додаткову підтримку старих версій IE.
Pointy

2
У MDN є досить хороший запис на маніпуляцію історією браузера
sachleen

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

3
За словами Mozilla , titleпараметр насправді не використовується.
Ракета Хазмат

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

Відповіді:


68

Дійсно, це помилка, хоча навмисна вже 2 роки. Проблема полягає в деяких незрозумілих характеристиках та складності, коли document.titleзадіяні та назад / вперед.

Дивіться посилання на помилки на веб- сайтах Webkit та Mozilla . Також Opera при введенні історії API заявила, що не використовує параметр title, і, ймовірно, все ще не працює.

В даний час 2-й аргумент pushState і substituState - заголовок запису історії - не використовується в реалізації Opera, але може бути один день.

Потенційне рішення

Єдиний спосіб, який я бачу, - це змінити заголовний елемент і використовувати замість pushState:

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

Для користувачів jquery .. спробуйте $ ("title"). Html (_title);
suraj jain

3
це може призвести до того, що користувачі потребують "подвійного клацання" кнопки "назад", залежно від того, як ви це реалізуєте. Більш простим рішенням може бути продовження використання replaceState()та просто встановлення заголовка документа вручнуdocument.title = "title"
новинних коротів

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 змінюється, але заголовок не змінюється .. протестовано останнім хромом @trott
Serjas

6
@Serjas titleПараметр в 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" замість "substituState"?
Giwrgos Tsopanoglou

1
@GiwrgosTsopanoglou: Я відповів на це рік тому, тому я не впевнений, чому :-P У будь-якому випадку, replaceStateзмінює поточний стан сторінки. Це дозволяє змінювати об'єкт стану та URL-адресу поточного стану сторінки.
Ракета Hazmat

2
Просто дивно, що я шукав інформацію про заміну, і я закінчив читати про 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 : "Переміщує дані в історію сеансу із заданим заголовком" . Дані в цій фразі є даними про стан , тому знову заголовок стосується стану (даних).
Stephen P

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 відкриває PR проти
реагуючого

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.