От автора: бывают ситуации, когда нам может пригодиться сохранение ссылок на последние в приложении Vue js маршруты, которые посетил пользователь. Например, предположим, что мы работаем с многошаговой формой, и пользователь переходит от одного шага к следующему. Было бы идеально иметь под рукой маршрут этого предыдущего шага, чтобы мы знали, где остановился пользователь, в случае, если он уйдет и вернется, чтобы заполнить форму позже.
Мы расскажем, как сохранить последний известный маршрут, а затем получить его, когда нам это нужно. В этом примере мы будем работать с Vue и добавим vue-router для маршрутизации, а localStorage — для хранения информации о последнем посещенном маршруте. Вот пример того, с чем мы будем работать:
Сначала давайте наметим структуру маршрутов. В нашем примере всего три маршрута:
/home
/hello
/goodbye
Каждому маршруту должно быть присвоено свойство name, поэтому давайте добавим это в наш файл router.js:
// router.js import Vue from "vue"; import Router from "vue-router"; import Hello from "@/components/Hello"; import Goodbye from "@/components/Goodbye"; import { HELLO_URL, GOODBYE_URL } from "@/consts"; Vue.use(Router); const router = new Router({ mode: "history", routes: [ { path: "/", name: "home" }, { path: HELLO_URL, name: "hello", component: Hello }, { path: GOODBYE_URL, name: "goodbye", component: Goodbye } ] }); export default router;
Далее давайте рассмотрим требования
Мы знаем, что первым требованием является сохранение последнего посещенного маршрута в localStorage. И, во-вторых, мы должны быть в состоянии найти его. Но при каких условия следует выбирать и применять маршрут? Это дает нам два дополнительных требования.
пользователь входит в основной маршрут (/home), уходит с него и хочет вернуться к нему.
пользователь был неактивен в течение определенного периода времени, сеанс истекает, и мы хотим вернуть пользователя к последнему окну, на котором он был после перезапуска сеанса.
Эти четыре требования — то, что нам нужно выполнить, чтобы продолжить перенаправление. Теперь давайте перейдем к коду.
Требование 1: Сохранить последнее имя маршрута в localStorage
Мы хотим сохранить ссылку на последний посещенный маршрут в localStorage. Например, если пользователь находится на /checkout, а затем покидает его, мы хотим сохранить его, чтобы покупка могла быть завершена позже.
Для этого мы хотим сохранить имя маршрута, когда пользователь вводит любой новый маршрут. Мы будем использовать гард навигации, называемый afterEach, который запускается каждый раз , когда переход маршрута закончен. Он предоставляет объект to, который является целевым объектом маршрута. В этом хуке, мы можем извлечь имя этого маршрута и сохранить его в localStorage с помощью метода setItem.
// router.js const router = new Router( ... ); router.afterEach(to => { localStorage.setItem(LS_ROUTE_KEY, to.name); }); ... export default router;
Требование 2: получить последнее имя маршрута из localStorage и перенаправить пользователя
Теперь, когда имя последнего маршрута сохранено, нам нужно иметь возможность извлечь его и вызвать на него перенаправление, когда это необходимо. Мы хотим проверить, следует ли выполнять перенаправление, прежде чем мы введем новый маршрут, поэтому мы будем использовать другой гард навигации — beforeEach. Этот гард получает три аргумента:
to: целевой объект маршрута
from: текущий маршрут с которого выполняется переход
next: функция, которая должна вызываться в гарде, чтобы разрешить хук
В этом гарде мы читаем имя последнего посещенного маршрута, используя метод localStorage.getItem(). Затем мы определяем, следует ли перенаправлять пользователя. На этом этапе мы проверяем, что целевой маршрут (to) является нашим основным маршрутом (/home), и действительно ли у нас есть последний маршрут в localStorage.
Если эти условия соблюдены, мы запускаем метод next, который содержит название последнего посещенного маршрута. Это, в свою очередь, вызовет перенаправление на этот маршрут.
Если какое-либо условие не выполнено, мы запускаем next без аргументов. Это переместит пользователя к следующему хуку в конвейере и продолжит обычную маршрутизацию без перенаправления.
// router.js const router = new Router( ... ); router.beforeEach((to, from, next) => { const lastRouteName = localStorage.getItem(LS_ROUTE_KEY); const shouldRedirect = Boolean( to.name === "home" && lastRouteName ); if (shouldRedirect) next({ name: lastRouteName }); else next(); }); ... export default router;
Это охватывает два из четырех требований! Давайте продолжим с требованием номер три.
Требование 3: Условие первого посещения
Теперь нам нужно проверить, посещает ли пользователь основной маршрут впервые (приходит из другого источника) или перемещается туда с другого маршрута в приложении. Мы можем сделать это, добавив флаг, для которого устанавливается true при создании маршрутизатора, и false после завершения первого перехода.
// router.js const router = new Router( ... ); let isFirstTransition = true; router.beforeEach((to, from, next) => { const lastRouteName = localStorage.getItem(LS_ROUTE_KEY); const shouldRedirect = Boolean( to.name === "home" && && lastRouteName && isFirstTransition ); if (shouldRedirect) next({ name: lastRouteName }); else next(); isFirstTransition = false; }); ... export default router;
Хорошо, есть еще одно требование, которое мы должны выполнить: мы хотим перенаправить пользователя на последний известный маршрут, если пользователь был неактивен дольше определенного периода времени.
Требование 4: условие времени активности
Опять же, мы будем использовать localStorage, чтобы сохранить информацию о последнем посещенном маршруте пользователя.
В гарде beforeEach мы получим маршрут из localStorage и проверим, находится ли время, прошедшее с этого момента, в пределах нашего порога (определяемого как hasBeenActiveRecently). Затем, в shouldRedirect, мы определим, должно ли произойти перенаправление маршрута или нет.
Нам также нужно сохранить ту информацию, которую мы получаем из гарда afterEach.
// router.js const router = new Router( ... ); let isFirstTransition = true; router.beforeEach((to, from, next) => { const lastRouteName = localStorage.getItem(LS_ROUTE_KEY); const lastActivityAt = localStorage.getItem(LS_LAST_ACTIVITY_AT_KEY); const hasBeenActiveRecently = Boolean( lastActivityAt && Date.now() - Number(lastActivityAt) < MAX_TIME_TO_RETURN ); const shouldRedirect = Boolean( to.name === "home" && && lastRouteName && isFirstTransition && hasBeenActiveRecently ); if (shouldRedirect) next({ name: lastRouteName }); else next(); isFirstTransition = false; }); router.afterEach(to => { localStorage.setItem(LS_ROUTE_KEY, to.name); localStorage.setItem(LS_LAST_ACTIVITY_AT_KEY, Date.now()); }); ... export default router;
Мы выполнили требования!
Вот и все! Мы охватили все четыре требования, а именно:
Мы храним последний посещенный маршрут в localStorage
У нас есть метод, чтобы получить последний посещенный маршрут из localStorage
Мы перенаправляем пользователя обратно на основной маршрут, если он входит в приложение при первом посещении.
Мы предоставляем пользователю перенаправление на последний известный маршрут в течение определенного периода времени.
Конечно, мы можем расширить это, добавив приложению больше сложности и новые условия для переменной shouldRedirect, но это дает нам больше, чем нужно, чтобы понять, как сохранить последний посещенный маршрут и получить его, когда это необходимо.
Автор: Mateusz Rybczonek
Источник: https://css-tricks.com/
Редакция: Команда webformyself.