Javascript роутер в 90 строк

Перевод статьи A modern JavaScript router in 100 lines

Требования:
Роутер должен:

  1. содержать меньше 100 строк
  2. поддерживать url с хэшами
  3. работать с History API
  4. предоставлять простой API интерфейс
  5. запускаться вручную
  6. отрабатывать только в тех случаях когда это необходимо

Модуль синглтон

  • routes – хранит список зарегистрированных точек
  • mode – может принимать значение hash или history в зависимости от поддержки History API
  • root – корневая точка приложения, необходима только при использовании pushState

Настройки
Метод для первичной настройки принимает два параметра, можно передать их в одном объекте.

Режим ‘history’ будет включен только в том случае если передать необходимый параметр и при условии что браузер поддерживает pushState.

Разобрать текущий URL

Метод без которого соответственно ничего не заработает, отвечает за определение текущего адреса. Так как роутер работает в одном из двух режимов, то и обрабатывать url будем по разному.

В обоих случаях определение URL происходит на основе глобального window.location. В режиме ‘history’, надо удалить корневую часть url. И все get параметры, при помощи регулярного выражения (/\?(.*)$/). Кроме того метод clearSlashes который удаляет слэши в начале и конце, для того чтобы унифицировать адрес, пользователь может вводить адрес со слэшем или без, мы всегда получим одинаковое значение.

Добавление и удаление маршрутов

Пока я работал над AbsurdJS то всегда старался дать как можно больше свободы разработчикам. В большинстве js роутеров которые я встречал, сравнение работало на основании строки. но мне кажется применение регулярных выражений предоставляет намного больше возможностей.

Метод add наполняет массив маршрутов, путём передачи параметров: путь, обработчик. В случае если на вход add дан только один параметр и этот параметр функция, то считать эту функцию (колбэк) обработчиком корневого маршрута. Кстати, вы заметили, что почти все методы возвращают this, это позволяет строить цепочки вызовов.

Удаление маршрута произойдёт только в том случае, если передать точно такое же регулярное выражение или функцию обрабочик.

Если вдруг понадобится сбросить все настройки, для этого есть метод flush, который сбрасывает список маршрутов и режим работы.

Check-in

Итак, выше определены методы для выявления текущего адреса, добавления и удаления маршрутов. Следующим логическим шагом будет создание метода для сравнения текущего адреса и зарегистрированных маршрутов.

Метод check в качестве параметра получает url, если параметр пуст, то при помощи getFragment, потом проходит по всем зарегистрированным маршрутам и сверяет с полученным фрагментом, при совпадении запускает callback передавая в него динамические части маршрута.

На выходе в консоли:

Контроль изменений адреса

Так как нельзя постоянно находится в состоянии прослушки изменений, необходим какой-то триггер изменений в адресной строке, даже в том числе если пользователь нажал кнопку “назад”. В History API существует событие popstate, которое вызывает браузер при изменении адреса страницы, но некоторые браузеры вызывают это событие и при первичной загрузке сайта. Дабы сделать везде работу одинаковой мне пришлось придумать другой способ, использование setInterval.

Храним последний активный url, чтобы сравнить с новым.

Changing the URL

Наконец роутеру недостаёт возможности самостоятельно менять адрес.

Ещё раз, если браузер поддерживает History API и вы выбран режим history, то можно использовать pushstate, иначе старый добрый друг window.location.

Полный скрипт и небольшой пример

Leave a Reply

Your email address will not be published. Required fields are marked *