Метод history.pushState() в JavaScript — история браузера

В этом руководстве вы узнаете, как использовать метод JavaScript history.pushState().

Метод history.pushState() позволяет добавить запись в стек истории сеансов веб-браузера.

Синтаксис:

history.pushState(state, title, [,url])

Метод принимает три параметра:

1) state

state — сериализуемый объект. При переходе в новое состояние запускается событие popstate . А событие popstate имеет свойство state , которое ссылается на объект state записи истории.

2) title

Большинство браузеров в настоящее время используют это свойство title. Если вы хотите изменить заголовок документа, вы можете вместо этого использовать свойство documen.title .

На практике вы передаете пустую строку параметру title .

3) url

Необязательный url позволяет вам определить URL-адрес новой записи в истории. URL-адрес должен иметь то же происхождение, что и текущий URL-адрес, иначе метод вызовет исключение.

Когда вы устанавливаете новые url , веб-браузер не будет загружать url . По умолчанию url использует текущий URL-адрес, если вы его не укажете.

Пример

Мы создадим простое приложение с тремя вкладками: React, Vue и Angular.

При нажатии на вкладку отображается содержимое выбранной вкладки. он также обновится URL-адрес, используя метод history.pushState() :

Пример с методом history.pushState()

Если вы скопируете URL-адрес с хэштегом и загрузите его из веб-браузера, приложение загрузит соответствующий контент, связанный с этим URL-адресом.

Страница index.html

Следующий код определяет страницу index.html :

<!DOCTYPE html>
<html lang="en">
	<head>
		<meta charset="UTF-8" />
		<meta name="viewport" content="width=device-width, initial-scale=1.0" />
		<title>JavaScript History API: pushState Demo</title>
		<link rel="stylesheet" href="css/style.css" />
	</head>

	<body>
		<div class="container">
			<div class="tabs">
				<ul>
					<li class="active" id="tab1">React</li>
					<li id="tab2">Vue</li>
					<li id="tab3">Angular</li>
				</ul>
				<div class="content">
					A JavaScript library for building user interfaces
				</div>
			</div>
		</div>

		<script src="js/app.js"></script>
	</body>
</html>

В файле app.js :

  • Сначала выберите вкладки и элементы контента, используя метод querySelector() :
const tabs = document.querySelector(".tabs");
const content = document.querySelector(".tabs &gt; .content");
  • Во-вторых, определите объект карты, который связывает хэш URL с идентификатором каждой вкладки:
const hashes = new Map([
    ["#react", "tab1"],
    ["#vue", "tab2"],
    ["#angular", "tab3"],
]);
  • В-третьих, определите другую карту, называемую данными, для сопоставления идентификатора вкладки с объектом. Объект имеет два свойства: url и content .
const data = new Map([
    [
        "tab1",
        {
            url: "index.html#react",
            content:
                "React is a JavaScript library for building user interfaces.",
        },
    ],
    [
        "tab2",
        {
            url: "index.html#vue",
            content: "Vue is the Progressive JavaScript Framework.",
        },
    ],
    [
        "tab3",
        {
            url: "index.html#angular",
            content:
                "Angular is a platform for building mobile and desktop web applications.",
        },
    ],
]);
  • В-четвертых, при нажатии каждой вкладки (или элемента li) происходит событие click . Чтобы сделать его более эффективным, мы будем использовать делегирование событий.

Поэтому вместо обработки события click на каждой вкладке мы будем обрабатывать событие click на родительском элементе каждой вкладки:

tabs.addEventListener("click", function (event) {
    if (!event.target.id) return;
    update(event.target.id);
});

Оператор if гарантирует, что обработчик событий обновит содержимое и URL-адрес только в том случае, если событие click произойдет на каждой отдельной вкладке. Ничего не произойдет, когда вы щелкнете по области содержимого вкладки.

Внутри обработчика события мы вызываем функцию update() и передаем ей идентификатор вкладки.

  • В-пятых, следующее определяет функцию update() :
const update = (tabId) =&gt; {
    // remove the active class of the previously selected tab
    const currentTab = tabs.querySelector(".active");

    if (currentTab.id != tabId) {
        currentTab.classList.remove("active");
    }
    // add active class to the selected tab
    const selectedTab = document.getElementById(tabId);
    selectedTab.classList.add("active");

    const entry = data.get(tabId);

    if (entry) {
        // update the URL
        history.pushState(null, "", entry.url);
        // change the content
        content.innerHTML = entry.content;
    }
};

Функция update() удаляет класс .active с текущей вкладки и устанавливает тот же класс CSS для текущей выбранной вкладки.

Она также получает URL-адрес и контент из данных на основе идентификатора вкладки. Для обновления URL используется метод history.pushState() .

Приложение должно работать должным образом только с одной проблемой.

Если вы скопируете URL-адрес:

https://www.javascripttutorial.net/sample/webapis/history/index.html#angular

… и вставьте его в новое окно браузера, приложение отобразит вкладку React вместо вкладки Angular .

Чтобы исправить это, мы получаем хеш из URL с помощью объекта location и вызываем функцию update() при загрузке страницы.

(() =&gt; {
    // get tab id from the hash
    const tabId = hashes.get(window.location.hash);
    // update the tab
    if (tabId) update(tabId);
})();

Ниже показан полный файл app.js :

const tabs = document.querySelector(".tabs");
const content = document.querySelector(".tabs &gt; .content");

// store the relationship between hash &amp; tab id
const hashes = new Map([
    ["#react", "tab1"],
    ["#vue", "tab2"],
    ["#angular", "tab3"],
]);

// store the relationship between tab id and contents
const data = new Map([
    [
        "tab1",
        {
            url: "index.html#react",
            content:
                "React is a JavaScript library for building user interfaces.",
        },
    ],
    [
        "tab2",
        {
            url: "index.html#vue",
            content: "Vue is the Progressive JavaScript Framework.",
        },
    ],
    [
        "tab3",
        {
            url: "index.html#angular",
            content:
                "Angular is a platform for building mobile and desktop web applications.",
        },
    ],
]);

tabs.addEventListener("click", function (event) {
    if (!event.target.id) return;
    update(event.target.id);
});

const update = (tabId) =&gt; {
    // remove the active class of the previously selected tab
    const currentTab = tabs.querySelector(".active");

    if (currentTab.id != tabId) {
        currentTab.classList.remove("active");
    }
    // add active class to the selected tab
    const selectedTab = document.getElementById(tabId);
    selectedTab.classList.add("active");

    const entry = data.get(tabId);

    if (entry) {
        // update the URL
        history.pushState(null, "", entry.url);
        // change the content
        content.innerHTML = entry.content;
    }
};

(() =&gt; {
    // get tab id from the hash
    const tabId = hashes.get(window.location.hash);
    // update the tab
    if (tabId) update(tabId);
})();
Рейтинг
( Пока оценок нет )
Александр Русаков / автор статьи
Программист, разработчик, 12 лет опыта работы в крупных компаниях. Быстро освоил typescript, делюсь своими знаниями на страницах этого сайта.
Загрузка ...
JavaScript и TypeScript