В настоящее время все три мастера внешнего интерфейса Angular, React и Vue рекомендуют режим разработки одностраничного приложения SPA, который заменяет минимально измененную часть DOM в дереве DOM при переключении маршрута, чтобы уменьшить огромную потерю производительности. вызвано переходом на страницу многостраничного приложения. У всех есть свои типовые решения маршрутизации, @angular/router, react-router, vue-router.
Как правило, эти плагины маршрутизации всегда предоставляют два разных метода маршрутизации: Hash и History, а иногда также предоставляют методы маршрутизации в небраузерных средах.Внешний вид РежимПредоставляет согласованный высокоуровневый интерфейс для нескольких различных методов маршрутизации, что позволяет нам переключаться между различными методами маршрутизации более развязанно.
Стоит отметить, что помимо разницы во внешнем виде между Hash и History есть еще одно отличие: сохранение состояния метода Hash нужно передавать отдельно, в то время как HTML5 History изначально предоставляет возможность настраивать передачу состояния, мы можем напрямую использовать это Отправить сообщение.
Давайте подробно рассмотрим характеристики этих двух методов и предоставим простую реализацию, более сложные функции, такие как ленивая загрузка, динамическое сопоставление путей, вложенная маршрутизация, псевдонимы маршрутизации и т. д., вы можете обратить внимание на источник vue-router код позади Читать блог.
Заинтересованные студенты могут добавить группу WeChat в конце статьи для совместного обсуждения~
1. Hash
1.1 Связанные API
Метод Hash маршрутизируется с#
, главный принцип - следить#
Браузер запускается изменением идентификатора пути URL послеhashchange
событие, то получитеlocation.hash
Получите идентификатор текущего пути, а затем выполните некоторые операции перехода маршрутизации, см.MDN
-
location.href
: возвращает полный URL -
location.hash
: возвращает якорную часть URL -
location.pathname
: возвращает URL-адрес пути -
hashchange
событие: когдаlocation.hash
Когда произойдет изменение, это событие будет запущено
Например, чтобы открыть путьhttp://sherlocked93.club/base/#/page1
, то вышеуказанные значения равны:
# http://sherlocked93.club/base/#/page1
{
"href": "http://sherlocked93.club/base/#/page1",
"pathname": "/base/",
"hash": "#/page1"
}
Уведомление:Метод Hash использует функцию, эквивалентную привязке страницы, поэтому он конфликтует с исходным методом прокрутки и позиционирования страницы посредством позиционирования привязки, что приводит к неправильному пути маршрутизации, поэтому необходимо использовать другой метод.progress-catalogЭтот плагин сталкивается с этой ситуацией.
1.2 Примеры
Вот простая реализация Принцип состоит в том, чтобы записать целевой маршрут и соответствующий обратный вызов, а затем щелкнуть, чтобы перейти к срабатыванию.hashchange
Когда текущий путь получен и соответствующий обратный вызов выполняется, эффект выглядит следующим образом:
class RouterClass {
constructor() {
this.routes = {} // 记录路径标识符对应的cb
this.currentUrl = '' // 记录hash只为方便执行cb
window.addEventListener('load', () => this.render())
window.addEventListener('hashchange', () => this.render())
}
/* 初始化 */
static init() {
window.Router = new RouterClass()
}
/* 注册路由和回调 */
route(path, cb) {
this.routes[path] = cb || function() {}
}
/* 记录当前hash,执行cb */
render() {
this.currentUrl = location.hash.slice(1) || '/'
this.routes[this.currentUrl]()
}
}
Ссылка на конкретную реализациюCodePen
Если вы хотите использовать сценарий для управления задней частью маршрута Hash, вы можете записать маршрут, который вы испытали.Реализация обратного перехода по маршруту правильная.location.hash
Сделайте задание. Но это вызовет повторный бросокhashchange
мероприятие, вторая записьrender
. Поэтому нам нужно добавить бит флага, чтобы указать записьrender
Этот метод связан с резервной записью или переходом пользователя
class RouterClass {
constructor() {
this.isBack = false
this.routes = {} // 记录路径标识符对应的cb
this.currentUrl = '' // 记录hash只为方便执行cb
this.historyStack = [] // hash栈
window.addEventListener('load', () => this.render())
window.addEventListener('hashchange', () => this.render())
}
/* 初始化 */
static init() {
window.Router = new RouterClass()
}
/* 记录path对应cb */
route(path, cb) {
this.routes[path] = cb || function() {}
}
/* 入栈当前hash,执行cb */
render() {
if (this.isBack) { // 如果是由backoff进入,则置false之后return
this.isBack = false // 其他操作在backoff方法中已经做了
return
}
this.currentUrl = location.hash.slice(1) || '/'
this.historyStack.push(this.currentUrl)
this.routes[this.currentUrl]()
}
/* 路由后退 */
back() {
this.isBack = true
this.historyStack.pop() // 移除当前hash,回退到上一个
const { length } = this.historyStack
if (!length) return
let prev = this.historyStack[length - 1] // 拿到要回退到的目标hash
location.hash = `#${ prev }`
this.currentUrl = prev
this.routes[prev]() // 执行对应cb
}
}
Справочник по реализации кодаCodePen
2. HTML5 History Api
2.1 Связанные API
HTML5 предоставляет несколько API для операций маршрутизации.В этой статье о MDN приведен список часто используемых API и их функций. Конкретные параметры не представлены. Все они доступны на MDN.
-
history.go(n)
: Маршрутный переход, например, n2
это перейти на 2 страницы вперед, n это-2
— вернуться на 2 страницы назад, n — 0 — обновить страницу -
history.back()
: Маршрут назад, эквивалентноhistory.go(-1)
-
history.forward()
: маршрут вперед, эквивалентныйhistory.go(1)
-
history.pushState()
: добавьте историю маршрутизации, если вы установите междоменный URL-адрес, будет сообщено об ошибке -
history.replaceState()
: заменить информацию в истории маршрутизации текущей страницы -
popstate
Событие: срабатывает при изменении истории активности.popstate
Событие также запускается при нажатии кнопок браузера вперед и назад или при вызове первых трех методов, описанных выше.MDN
2.2 Примеры
Измените предыдущий пример и используйте его там, где требуются переходы маршрутизации.history.pushState
нажать и записатьcb
, контролировать при движении вперед и назадpopstate
Событие передается доpushState
параметры и выполнить соответствующиеcb
, потому что собственный API браузера заимствован, поэтому код выглядит намного чище
class RouterClass {
constructor(path) {
this.routes = {} // 记录路径标识符对应的cb
history.replaceState({ path }, null, path) // 进入状态
this.routes[path] && this.routes[path]()
window.addEventListener('popstate', e => {
const path = e.state && e.state.path
this.routes[path] && this.routes[path]()
})
}
/* 初始化 */
static init() {
window.Router = new RouterClass(location.pathname)
}
/* 注册路由和回调 */
route(path, cb) {
this.routes[path] = cb || function() {}
}
/* 跳转路由,并触发路由对应回调 */
go(path) {
history.pushState({ path }, null, path)
this.routes[path] && this.routes[path]()
}
}
Режим хеширования заключается в использовании хэша URL-адреса для имитации полного URL-адреса, чтобы страница не перезагружалась при изменении URL-адреса. Режим истории будет напрямую изменять URL-адрес, поэтому некоторая информация об адресе будет потеряна при переходе маршрута, а статические ресурсы не будут сопоставляться при обновлении или прямом доступе к адресу маршрута. Поэтому на сервере необходимо настроить некоторую информацию, чтобы сервер мог добавить ресурс-кандидат, который охватывает все ситуации, такие как прыжкиindex.html
Что, вообще говоря, это страница, от которой зависит ваше приложение.На самом деле библиотеки, такие как vue-router, также рекомендуются, а также предоставляют общиеконфигурация сервера.
Справочник по реализации кодаCodePen
Большинство сообщений в Интернете имеют разную глубину и даже некоторые несоответствия. Следующие статьи являются кратким изложением процесса обучения. Если вы найдете какие-либо ошибки, пожалуйста, оставьте сообщение, чтобы указать ~
Ссылаться на:
PS: Всех приглашаю обратить внимание на мой публичный аккаунт [Front End Afternoon Tea], давайте работать вместе~
Кроме того, вы можете присоединиться к группе WeChat «Front-end Afternoon Tea Exchange Group», нажмите и удерживайте, чтобы определить QR-код ниже, чтобы добавить меня в друзья, обратите вниманиеДобавить группу, я заберу тебя в группу~