VUE дружим с Роутингом

С большими возможностями приходит и большая ответственность
! Человек паук

Сегодня мы разберем продвинутые техники идеального укрощения роутинга в реактивном фреймворке на примере VUE. Если вы совершаете переход от обычных страниц к реактивности - можете наткнуться на несколько камней, которые мало где описаны как можно решать правильно.
В чем же особенность роутинга в реактивных приложениях. А в том, что страница не перегружается полностью а происходит эмуляция обновления страницы, а именно изменяющейся части. Мы же реактивные, информацию в шапке и других общих частях (которая обычно располагается в папке layouts) и это здорово, потому что браузеру не нужно заново рендерить эту самую неизменную область схожую у нескольких страниц заново. А URL эмулируется либо через хеш # либо через History API

И всё тут складно и всё красиво ровно до тех пор, пока мы не замечаем проблему при переходе с одной страницы роутинга на ту же самую страницу. И почему-то контент не ведет себя аналогичным образом, компонент page на который смотрит роутинг не выполняет методы жизненного цикла create и mount и отсюда имеем не то поведение которое от него ожидаем

Ранее проблемы не возникало потому что не было возможности сохранить страницу и обновить только изменяемую часть.

Можно решить задачу тупо в лоб. Снести всю реактивность и поставить методы как привыкли, назовем метод refresh(). Нужно обновить  - вешаем метод который всё что нужно обновит на каждое событие которое может привести к изменению. Вот досада - нативные методы вперед-назад теперь не откликаются. Тут без реактивности не обойтись. У нас же есть наблюдатели watch, в которые можно запихнуть роутинг и следить за его изменением. Теперь все методы обновления можно делегировать ему.

замечательно. Роутинг сам следит за обновлением, вешать ничего нигде не надо. Вперед-назад также работает
Ну а теперь представьте что вы делаете приложение немножко круче чем стандартный блог. И что, на каждой странице, вам нужно готовить функцию для обновления? Так прекрасно жили ранее когда не было таких проблем. Может ну его, этот роутинг, отказаться и все дела.

Для тех кто не сдался - в запасе есть еще пара фокусов. Мы же всё ещё в javascript мире. Нам всё ещё доступны window.reload()
Если честно, очень грязный трюк. Крайне не рекомендую. Лучше возьмите на вооружение что-нибудь полегче, например такое

const to = this.$router.currentRoute
this.$router.replace("/")
this.$nextTick(() => this.$router.replace(to))

(нарыл в лучших рекомендациях на stackoverflow)

а теперь давайте познакомимся с одной интересной возможностью VUE - атрибут :key. Вы часто встречали его в циклах и списках, но он также может использоваться и для обычных элементов. Зачем он нужен? Он используется чтобы совмещать DOM дерево с виртуальным DOM шаблоном. Или как-то так. В общем элементы с одинаковым :key внутри компонента приводят к ошибке и перестают адекватно реагировать на изменение реактивности. Дополнительно при изменении этого самого :key - будет перерендерен сам элемент со всеми вытекающими. В общем то что нам нужно.
Теперь осталось связать наш любимый роутинг с этим самым :key на отслеживание. Как это сделать? Проще простого.

<router-view :key="$route.path"></router-view>

или даже не

<router-view :key="$route.fullPath"></router-view>

нас же интересует изменение и гет параметров, поисков и всего такого
всё готово. В продакшн. (Это решение тоже было подсмотрено на просторах  stackoverflow, странно что в официальной документации такая базовая вещь не расписывается)

Хепи енд?
Смотрим что теперь получается. Теперь мы попали в другую крайность и стали заложниками маршрутизатора. При малейшем его изменении всегда и везде - будет обновление страницы (контента). Если у нас приложение сложнее чем портал с подстраницами 2го уровня и больше и общей шапкой, которую не нужно обновлять регулярно, чтобы экран не дергался, да и лишние запросы и нагрузка - вы же понимаете, мы обсуждали это всё чуть ранее. В общем не красиво это.
Это точно не хепи енд. И Даже nuxt тут не поможет

Теперь чтобы привнести мир в этом всё дело - мы можем просто добавить список исключений в параметр key для главного контента таким образом, чтобы он не менялся при переходе между подстраницами раздела. Сделать это можно легко с помощью computed выражения например с исключением на странице admin

<router-view :key="refreshablePath"></router-view>
computed: {
refreshablePath() {
// роут внутри admin исключение
if (this.$route.path.substr(0, 6) === "/admin") {
return this.$route.path.substr(0, 6)
}
return this.$route.fullPath
},
},

дополнительно на самой странице нужно повесить :key="$route.fullPath" на компоненте, который должен перенегеиться в зависимости от изменения роута внутри основной страницы.

да звучит хардкорно, и выглядит избыточно, чтобы для каждой такой страницы прописывать похожую конструкцию. Наверняка есть пусть элегантно уницифировать это на какие-нибудь нативные методы вроде meta тегов внутри роутов и какой-нибудь облегченной проверки через pathMatch
Об этом возможно вы услышите в следующей главе, или откопаете сами в качестве домашнего задания.

  • Автор: kosmom
  • Рейтинг: 0
  • Просмотров: 21
  • Комментариев: 0
  • Создан: 14.11.2020 05:37

Комментарии (0)