Создание быстрых и функциональных сайтов является проблемой, с которой знакомы большинство веб-разработчиков. Медленная загрузка новой страницы каждый раз, когда пользователь нажимает на ссылку. Извлечение всего содержимого динамически эффективно отключает кнопку «Назад». Работать с хешами лучше, но все же не идеально. Internet Explorer 10 в Windows Developer Preview устраняет компромисс, добавляя поддержку истории HTML5 . PushState , replaceState и popstate интерфейсы обеспечивают точный контроль над поведением кнопки возврата и URL представлена пользователю для динамического контента. Вместе эти API помогут вам повысить производительность вашего сайта, не жертвуя удобством использования.
Если вы еще не знакомы с API истории HTML5, представьте, что pushState является динамическим эквивалентом перехода на другую страницу. Точно так же replaceState очень похож на location.replace . Разница в том, что эти API оставляют текущую страницу нетронутой при обновлении истории сеанса , сохраняя состояния вместо страниц. И pushState, и replaceState принимают три параметра: объект данных, заголовок и необязательный URL-адрес.
history.pushState(data, title, url); history.replaceState(data, title, url);
Обратите внимание, что параметр title для pushState и replaceState игнорируется большинством браузеров, включая IE10. Если вы хотите, вы все равно можете предоставить эту информацию, поскольку будущие браузеры могут предоставлять ее как часть своего пользовательского интерфейса истории.
Настройка пользовательских URL
Параметр URL для pushState и replaceState можно использовать для обновления URL страницы без навигации. Для иллюстрации рассмотрим, что вы загрузили «http://www.contoso.com/index.html». Используя изменения хеша, вы можете добавить только URL:
// Change to "http://www.contoso.com/index.html#about.html" location.hash = "about.html";
Но с помощью pushState и replaceState вы можете указывать на совершенно другую страницу вашего сайта, фактически не заходя туда:
// Change to "http://www.contoso.com/about.html" history.pushState(null, "About", "/about.html");
Убедитесь, что ваш сервер может обрабатывать все динамические URL, которые вы создаете, чтобы такие вещи, как избранное, все еще работали. Вы также можете добавить некоторые данные в объект состояния, чтобы вам не приходилось позже анализировать полный URL-адрес, чтобы восстановить состояние:
history.pushState("about.html", "About", "/about.html");
Протокол, имя хоста и порт должны соответствовать текущему URL, но путь, запрос и фрагмент являются подходящей игрой для настройки. Это позволяет связывать динамические состояния с URL-адресами, которые легко поддерживаются сервером и работают, даже если скрипт отключен. В конечном счете, это позволяет динамически извлекать и отображать только данные, которые меняются от страницы к странице, сохраняя при этом пользовательский опыт без изменений.
Восстановление сохраненных состояний
Вы должны восстановить состояние после навигации по истории (например, когда пользователь нажимает кнопку «Назад») или перезагрузки страницы. Восстановление состояния выполняется путем прослушивания события popstate . В событии popstate пожары при изменении состояния в результате истории навигации. На этом этапе объект данных для состояния назначения может быть получен через history.state . В случаях, когда страница перезагружается, событие popstate не срабатывает, но к history.state все равно можно получить доступ в любое время во время или даже после загрузки. Таким образом, код, подобный следующему, может восстановить состояние в соответствующее время:
function init() { /* ... */ // Handle page load and reload loadState(); // Listen for history navigations (e.g. the back button) window.addEventListener("popstate", loadState, false); } function loadState() { // Grab the data for the current state so we can restore it var state = history.state; /* ... */ } init();
Хранение сложных динамических данных
Объект данных, хранящийся в состоянии, может быть больше, чем строка. Также можно использовать пользовательские объекты JavaScript и даже некоторые нативные типы, такие как ImageData . Предоставленные данные сохраняются с использованием алгоритма структурированного клонирования , который сохраняет сложные отношения, такие как циклы и множественные ссылки на один и тот же объект. Это делает сохранение и восстановление даже сложных объектов быстрым, как показано в этом простом демо . В демонстрационной версии снимки холста собираются для создания стека отмены с использованием кода, подобного следующему:
function init() { /* ... */ // Handle page load and reload loadState(); // Listen for history navigations (e.g. the back button) window.addEventListener("popstate", loadState, false); } /* ... */ function stopDrawing() { // Take a snapshot of the current state as an ImageData instance var state = context.getImageData(0, 0, canvas.width, canvas.height); history.pushState(state, ""); /* ... */ } function loadState() { // Grab the data for the current state so we can restore it var state = history.state; /* ... */ if (state) { // Restore the canvas to our saved ImageData state context.putImageData(state, 0, 0); } }
Чтобы изменить это, чтобы отслеживать текущее состояние без отслеживания каждого изменения, вы можете использовать replaceState вместо pushState .
Размер соображения
История HTML5 позволяет легко помещать большие объемы данных в стек, если вы не будете осторожны. Например, вышеприведенная демонстрация отмены хранит ~ 0,5 МБ на состояние и может легко использовать больше, если холст будет больше. Эти данные будут занимать память до тех пор, пока соответствующая запись состояния остается в истории сеанса, что может продолжаться долго после того, как пользователь покидает ваш сайт. Чем больше данных вы храните, тем скорее браузер может начать очищать ваши записи, чтобы сэкономить место. Кроме того, некоторые браузеры также устанавливают жесткое ограничение на объем данных, которые могут быть сохранены с помощью одного вызова pushState или replaceState .
Кросс-браузерные соображения
Как всегда, используйте функцию обнаружения для обработки различий в поддержке в разных браузерах. Поскольку большая часть истории HTML5 включает события и свойства, единственными новыми частями, которые действительно требуют обнаружения, являются вызовы pushState и replaceState :
function stopDrawing() { var state = context.getImageData(0, 0, canvas.width, canvas.height); if (history.pushState) history.pushState(state, ""); /* ... */ }
Такое обнаружение по крайней мере предотвратит сбой вашего скрипта в старых браузерах. В зависимости от вашего сценария вы можете начать с полностраничных переходов и перейти на динамический контент, если поддерживается история HTML5. Кроме того, вы можете использовать каркас истории или полизаполнение, чтобы кнопка возврата работала, но имейте в виду, что не все можно эмулировать. Например, динамическое управление компонентами пути и запроса URL-адреса может быть достигнуто только с помощью pushState и replaceState .
Обратите внимание, что некоторые браузеры поддерживают более раннюю версию истории HTML5 с двумя заметными отличиями от текущей версии:
- В popstate событие срабатывает даже во время загрузки страницы
- Свойство history.state не существует
Для поддержки этих браузеров вы можете вернуться к чтению информации о состоянии самого события popstate .
Заворачивать
В целом, API истории HTML5 обеспечивают большую гибкость для создания адаптивных и удобных веб-сайтов. С некоторой заботой об унаследованных браузерах, эти API могут быть использованы сегодня с большим эффектом. Начните тестировать их на своем сайте в IE10 в Windows Developer Preview и отправьте отзыв через Connect.