Основной принцип перехода к интерфейсной маршрутизации

JavaScript vue-router
Основной принцип перехода к интерфейсной маршрутизации

В настоящее время все три мастера внешнего интерфейса 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

  1. location.href: возвращает полный URL
  2. location.hash: возвращает якорную часть URL
  3. location.pathname: возвращает URL-адрес пути
  4. 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.

  1. history.go(n): Маршрутный переход, например, n2это перейти на 2 страницы вперед, n это-2— вернуться на 2 страницы назад, n — 0 — обновить страницу
  2. history.back(): Маршрут назад, эквивалентноhistory.go(-1)
  3. history.forward(): маршрут вперед, эквивалентныйhistory.go(1)
  4. history.pushState(): добавьте историю маршрутизации, если вы установите междоменный URL-адрес, будет сообщено об ошибке
  5. history.replaceState(): заменить информацию в истории маршрутизации текущей страницы
  6. 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


Большинство сообщений в Интернете имеют разную глубину и даже некоторые несоответствия. Следующие статьи являются кратким изложением процесса обучения. Если вы найдете какие-либо ошибки, пожалуйста, оставьте сообщение, чтобы указать ~

Ссылаться на:

  1. history | MDN
  2. hashchange | MDN
  3. Manipulating the browser history | MDN
  4. Основной принцип фронтенд-роутинга — Да Ши не говорит
  5. History Object -- Учебное пособие по стандарту JavaScript

PS: Всех приглашаю обратить внимание на мой публичный аккаунт [Front End Afternoon Tea], давайте работать вместе~

Кроме того, вы можете присоединиться к группе WeChat «Front-end Afternoon Tea Exchange Group», нажмите и удерживайте, чтобы определить QR-код ниже, чтобы добавить меня в друзья, обратите вниманиеДобавить группу, я заберу тебя в группу~