Что нужно знать о принципе реализации одностраничной маршрутизации

внешний интерфейс JavaScript HTML vue-router
Что нужно знать о принципе реализации одностраничной маршрутизации

предисловие

Недавно разработанный проект скрытой точки должен записывать отслеживание поведения пользователя, то есть последовательность доступа пользователя к странице. При переходе на страницу необходимо записывать информацию, к которой обращается пользователь (например, URL-адрес, заголовок запроса и т. д.).Неодностраничные приложения могут добавлять событие beforeunload к объекту окна, чтобы инициировать переключение захвата, когда страница уходит, но теперь многие предприятия для одностраничных приложений, когда пользователь переключает адреса, это частичное обновление без обновления, и нет возможности запустить перед выгрузкой. Следовательно, подключаемый модуль маршрутизации одностраничного приложения должен использовать метод, поставляемый с окном, для изменения записи просмотра пользователем без обновления, pushState и replaceState.

Узнайте о pushState и replaceState

history предоставляет два метода, которые могут изменять записи просмотров пользователя без обновления: pushSate и replaceState. Разница в том, что pushState добавляет запись доступа после страницы доступа пользователя, а replaceState напрямую заменяет текущую запись доступа.

Есть много хороших и подробных вводных документов для подробной информации об объекте истории.Мы не будем обобщать это здесь.Мы ссылаемся на введение учебника г-на Руана.объект истории -- Справочное руководство по стандарту JavaScript (альфа-версия)

history.pushState

Метод history.pushState принимает три параметра по порядку:

состояние: объект состояния, связанный с указанным URL-адресом. Когда событие popstate запускается, объект будет передан функции обратного вызова. Если вам не нужен этот объект, вы можете указать здесь null.

title: заголовок новой страницы, но в настоящее время все браузеры игнорируют это значение, поэтому здесь можно указать null.

URL-адрес: новый URL-адрес, который должен находиться в том же домене, что и текущая страница. Адресная строка вашего браузера отобразит этот URL. Предполагая, что текущий URL-адрес — example.com/1.html, мы используем метод pushState, чтобы добавить новую запись в запись просмотра (объект истории).

var stateObj = { foo: 'bar' };
history.pushState(stateObj, 'page 2', '2.html');

После добавления указанной выше новой записи в адресной строке браузера сразу отображается example.com/2.html, но он не переходит к 2.html и даже не проверяет, существует ли 2.html, он просто становится частью просмотра. история последняя запись. В это время вы вводите новый адрес в адресную строку (например, посетите google.com ), а затем нажимаете кнопку «Назад», URL-адрес страницы будет отображаться 2.html; если вы снова нажмете кнопку «Назад», URL-адрес будет отображаться 1.html.

Короче говоря, метод pushState не вызывает обновление страницы, а только вызывает изменение объекта истории и реакцию адресной строки.

Если параметр url pushState устанавливает новое значение привязки (т. е. хэш), событие hashchange не будет инициировано. Если задан междоменный URL, будет сообщено об ошибке.

// 报错
history.pushState(null, null, 'https://twitter.com/hello');

上面代码中,pushState想要插入一个跨域的网址,导致报错。这样设计的目的是,防止恶意代码让用户以为他们是在另一个网站上。

history.replaceState

Параметры метода history.replaceState точно такие же, как у метода pushState, разница в том, что он изменяет текущую запись в истории просмотров, предполагая, что текущая веб-страница — это example.com/example.html.

history.pushState({page: 1}, 'title 1', '?page=1');
history.pushState({page: 2}, 'title 2', '?page=2');
history.replaceState({page: 3}, 'title 3', '?page=3');

history.back()
// url显示为http://example.com/example.html?page=1

history.back()
// url显示为http://example.com/example.html

history.go(2)
// url显示为http://example.com/example.html?page=3

Скрытая точка отслеживания доступа пользователей к одностраничным приложениям

Учащиеся, разрабатывавшие одностраничные приложения, должны лучше знать, что переключение маршрутизации одностраничных приложений незаметно, и не будет повторно запрашивать http-запросы для получения страниц, а будет изменять вид рендеринга страницы. Таким образом, его принцип реализации также должен быть достигнут через нативное состояние pushState или replaceState. Поэтому при переходе на страницу необходимо вызвать pushState или replaceState.Чтобы записать информацию о переходе пользователя, нам нужно только перехватить pushState и replaceState и выполнить поведение по умолчанию.впередСначала выполните наш метод, чтобы собрать информацию о прыжке пользователя.

// 改写思路:拷贝 window 默认的 replaceState 函数,重写 history.replaceState 在方法里插入我们的采集行为,在重写的 replaceState 方法最后调用,window 默认的 replaceState 方法

collect = {}

collect.onPushStateCallback : function(){}  // 自定义的采集方法

(function(history){
    var replaceState = history.replaceState;   // 存储原生 replaceState
    history.replaceState = function(state, param) {     // 改写 replaceState
       var url = arguments[2];
       if (typeof collect.onPushStateCallback == "function") {
             collect.onPushStateCallback({state: state, param: param, url: url});   //自定义的采集行为方法
       }
       return replaceState.apply(history, arguments);    // 调用原生的 replaceState
    };
 })(window.history);

Реализация маршрутизации vue-router

Теперь, когда мы знаем этот принцип, давайте взглянем на реализацию vue-router, мы открываемадрес проекта vue-router,Клонируйте проект или просмотрите его прямо на github.В проекте, разработанном Vue, мы используем router.push('home') для реализации перехода на страницу, поэтому мы получаем реализацию метода push

查找push方法的实现

Мы извлекли 20 js файлов, 😂, в общем на это время мы откажемся от чтения исходников, тогда наша статья на сегодня окончена, спасибо!

Шучу, чтение исходного кода не может быть таким грубым, мы находим каталог src, нажимаем на файл index.js и видим, что определение объекта истории связано с параметром режима

if (!inBrowser) {
  mode = 'abstract'
}
this.mode = mode

switch (mode) {
  case 'history':
    this.history = new HTML5History(this, options.base)
    break
  case 'hash':
    this.history = new HashHistory(this, options.base, this.fallback)
    break
  case 'abstract':
    this.history = new AbstractHistory(this, options.base)
    break
  default:
    if (process.env.NODE_ENV !== 'production') {
      assert(false, `invalid mode: ${mode}`)
    }
}

Видя, что экземпляр объекта истории связан с настроенным режимом, vue-router реализует переключение маршрутизации тремя способами. Что соответствует тому, о чем мы говорим сегодня, так это реализация HTML5History. Другие не будут расширены в статье. Если вам интересно, вы можете прочитать расширенное чтение в конце статьи.

Давайте посмотрим на исходный код HTML5History в vue-router:

push (location: RawLocation, onComplete?: Function, onAbort?: Function) {
  const { current: fromRoute } = this
  this.transitionTo(location, route => {
    pushState(cleanPath(this.base + route.fullPath))
    handleScroll(this.router, route, fromRoute, false)
    onComplete && onComplete(route)
  }, onAbort)
}

replace (location: RawLocation, onComplete?: Function, onAbort?: Function) {
  const { current: fromRoute } = this
  this.transitionTo(location, route => {
    replaceState(cleanPath(this.base + route.fullPath))
    handleScroll(this.router, route, fromRoute, false)
    onComplete && onComplete(route)
  }, onAbort)
}

// src/util/push-state.js
export function pushState (url?: string, replace?: boolean) {
  saveScrollPosition()
  // try...catch the pushState call to get around Safari
  // DOM Exception 18 where it limits to 100 pushState calls
  const history = window.history
  try {
    if (replace) {
      history.replaceState({ key: _key }, '', url)
    } else {
      _key = genKey()
      history.pushState({ key: _key }, '', url)
    }
  } catch (e) {
    window.location[replace ? 'replace' : 'assign'](url)
  }
}

export function replaceState (url?: string) {
  pushState(url, true)
}

В процессе разработки с помощью Vue мы должны были использовать push и replace для изменения маршрутов и представлений.

Push, вызываемый экземпляром маршрутизатора, на самом деле является методом истории. Режим используется для определения схемы реализации, которая соответствует истории. Из кода видно, что push вызывает переписанный метод pushState в src/util/push-state.js. . Переданный метод будет определять, следует ли вызывать pushState или replaceState в соответствии с входящим параметром replace?: boolean, и одновременно делать захват ошибок. Если история не может изменить путь доступа без обновления, вызовитеwindow.location.replace(url), есть обновленный адрес доступа пользователя коммутатора, и то же самое верно для pushState. Основная функция метода transitionTo здесь заключается в обновлении представления и мониторинге перехода по маршруту.Если URL-адрес не меняется (не удается переключить адрес доступа), внутри метода transitionTo будет вызываться метод sureURL для изменения URL-адреса. В методе transitionTo используется много родительских методов, поэтому я не буду здесь вдаваться в длинное описание, а для конкретного анализа кода вы можете обратить внимание на мои будущие статьи.

Моделирование одностраничной маршрутизации

Из приведенного выше исследования мы знаем принцип реализации одностраничной маршрутизации приложений и пытаемся реализовать его. При создании системы управления мы обычно размещаем фиксированную боковую панель навигации в левой части страницы, а соответствующий основной контент — в правой части страницы. При нажатии на навигацию мы хотим, чтобы обновлялось только содержимое.Если вся страница обновляется, а навигация и общий заголовок и нижняя часть также перерисовываются и перестраиваются, это будет пустой тратой ресурсов, и опыт не будет хорошо. В настоящее время мы можем использовать то, что узнали сегодня, используя методы HTML5 pushState и replaceState для достижения,

Идея: сначала привяжите событие клика. Когда пользователь нажимает на ссылку, предотвращает поведение по умолчанию (переход на страницу) с помощью функции preventDefault при чтении адреса ссылки (если есть jQuery, его можно записать как(this).attr('href')),把这个地址通过pushState塞入浏览器历史记录中,再利用 AJAX 技术拉取(如果有 jQuery,可以使用.get) реальный контент по этому адресу и одновременно заменить контент текущей веб-страницы.

Чтобы обработать пользователя, идущего вперед и назад, мы прослушиваем событие popstate. Когда пользователь нажимает кнопку «вперед» или «назад», адрес браузера автоматически преобразуется в соответствующий адрес, и происходит событие popstate. В функции обработки событий мы захватываем соответствующий контент в соответствии с текущим адресом, а затем используем AJAX, чтобы получить реальный контент этого адреса и представить его.

Наконец, весь процесс не меняет заголовок страницы, вы можете изменить заголовок страницы, напрямую присвоив значение document.title.

расширять

Ну, сегодня мы говорили о методе pushState и применении replaceState во многих аспектах.У вас должно быть глубокое впечатление об этих двух методах.Если вы хотите узнать больше, вы можете обратиться к следующим ссылкам

объект истории -- Справочное руководство по стандарту JavaScript (альфа-версия)

Две реализации интерфейсной маршрутизации от vue-router