Es gibt Situationen, in denen es nützlich sein kann, eine Referenz auf die letzte Route zu behalten, die ein Benutzer besucht hat. Nehmen wir zum Beispiel an, wir arbeiten mit einem mehrstufigen Formular und der Benutzer schreitet von einem Schritt zum nächsten. Es wäre ideal, die Route dieses vorherigen Schritts zur Hand zu haben, damit wir wissen, wo der Benutzer aufgehört hat, falls er navigiert und später zurückkehrt, um das Formular später abzuschließen.

Wir werden behandeln, wie die letzte bekannte Route gespeichert und dann abgerufen wird, wenn wir sie benötigen. Wir arbeiten in diesem Beispiel mit Vue und verwenden vue-router für das Routing und localStorage, um die Informationen über die zuletzt besuchte Route zu speichern.
Hier ist ein Beispiel dafür, womit wir arbeiten werden
Zuerst skizzieren wir die Routenstruktur
Unser Beispiel hat insgesamt drei Routen
/home/hello/goodbye
Jede Route muss eine Namens-Eigenschaft zugewiesen bekommen, also fügen wir das unserer router.js-Datei hinzu
// 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;
Als Nächstes gehen wir die Anforderungen durch
Wir wissen, dass die erste Anforderung darin besteht, die zuletzt besuchte Route in localStorage zu speichern. Und zweitens müssen wir sie abrufen können. Aber unter welchen Bedingungen soll die Route abgerufen und angewendet werden? Das gibt uns zwei zusätzliche Anforderungen.
- der Benutzer die Hauptroute (
/home) betritt, von ihr weg navigiert und dann zurückkehren möchte. - der Benutzer für eine bestimmte Zeit inaktiv war, die Sitzung abläuft und wir den Benutzer nach dem Neustart der Sitzung zur letzten Ansicht zurückführen möchten.
Diese vier Anforderungen müssen wir erfüllen, um mit der Weiterleitung fortzufahren.
Springen wir nun zum Code.
Anforderung 1: Speichern des Namens der letzten Route in localStorage
Wir möchten die Referenz auf unsere zuletzt besuchte Route in localStorage speichern. Wenn ein Benutzer beispielsweise auf /checkout ist und die Seite verlässt, möchten wir dies speichern, damit der Kauf später abgeschlossen werden kann.
Dazu wollen wir den Routennamen speichern, wenn der Benutzer eine neue Route betritt. Wir verwenden einen Navigations-Guard namens afterEach, der jedes Mal ausgelöst wird, wenn der Routenübergang abgeschlossen ist. Er liefert ein to-Objekt, das das Ziel- Route-Objekt ist. In diesem Hook können wir den Namen dieser Route extrahieren und mit einer setItem-Methode in localStorage speichern.
// router.js
const router = new Router( ... );
router.afterEach(to => {
localStorage.setItem(LS_ROUTE_KEY, to.name);
});
...
export default router;
Anforderung 2: Abrufen des Namens der letzten Route aus localStorage und Weiterleitung
Nachdem nun der Name der letzten Route gespeichert ist, müssen wir ihn abrufen und eine Weiterleitung dazu auslösen, wenn er benötigt wird. Wir wollen prüfen, ob wir weiterleiten sollen, bevor wir eine neue Route betreten. Dazu verwenden wir einen weiteren Navigations-Guard namens beforeEach. Dieser Guard erhält drei Argumente
to: das Ziel-Route-Objektfrom: die aktuelle Route, von der navigiert wurdenext: die Funktion, die im Guard aufgerufen werden muss, um den Hook aufzulösen
In diesem Guard lesen wir den Namen der zuletzt besuchten Route mit einer localStorage.getItem()-Methode aus. Dann bestimmen wir, ob der Benutzer weitergeleitet werden soll. An diesem Punkt prüfen wir, ob die Zielroute (to) unsere Hauptroute (/home) ist und ob wir tatsächlich eine letzte Route in localStorage haben.
Wenn diese Bedingungen erfüllt sind, rufen wir die next-Methode auf, die den Namen der zuletzt besuchten Route enthält. Dies löst wiederum eine Weiterleitung zu dieser Route aus.
Wenn eine Bedingung fehlschlägt, rufen wir next ohne Argumente auf. Dies verschiebt den Benutzer zum nächsten Hook in der Pipeline und fährt mit dem normalen Routing ohne Weiterleitung fort.
// 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;
Damit sind zwei von vier Anforderungen erfüllt! Wir fahren mit Anforderung Nummer drei fort.
Anforderung 3: Die Bedingung für den ersten Besuch
Nun müssen wir prüfen, ob der Benutzer die Hauptroute zum ersten Mal besucht (aus einer anderen Quelle kommt) oder von einer anderen Route innerhalb der Anwendung dorthin navigiert. Das können wir tun, indem wir ein Flag hinzufügen, das auf true gesetzt wird, wenn der Router erstellt wird, und es nach Abschluss des ersten Übergangs auf false setzen.
// 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;
Okay, es gibt noch eine weitere Anforderung, die wir erfüllen müssen: Wir wollen den Benutzer zur letzten bekannten Route weiterleiten, wenn der Benutzer länger als ein bestimmter Zeitraum inaktiv war.
Anforderung 4: Die Bedingung für die Aktivitätszeit
Auch hier werden wir localStorage verwenden, um die Informationen über die zuletzt besuchte Route des Benutzers zu speichern.
Im beforeEach-Guard holen wir die Route aus localStorage und prüfen, ob die seit diesem Zeitpunkt vergangene Zeit innerhalb unserer Schwelle liegt (definiert durch hasBeenActiveRecently). Dann bestimmen wir in unserem shouldRedirect, ob eine Routenweiterleitung stattfinden soll oder nicht.
Wir müssen diese Informationen auch speichern, was wir im afterEach-Guard tun werden.
// 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;
Wir haben die Anforderungen erfüllt!
Das ist alles! Wir haben alle vier Anforderungen behandelt, nämlich
- Wir speichern die zuletzt besuchte Route in
localStorage - Wir haben eine Methode, um die zuletzt besuchte Route aus
localStorageabzurufen - Wir leiten einen Benutzer zur Hauptroute zurück, wenn er die Anwendung bei einem erstmaligen Besuch betritt
- Wir bieten dem Benutzer eine Weiterleitung zur zuletzt bekannten Route innerhalb eines bestimmten Zeitraums
Natürlich können wir dies weiter ausbauen, indem wir der App mehr Komplexität und der Variable shouldRedirect neue Bedingungen hinzufügen, aber dies gibt uns mehr als genug, um zu verstehen, wie wir die zuletzt besuchte Route persistent halten und bei Bedarf abrufen können.
Toller Artikel! Ich frage mich, warum wir dafür nicht die History API verwenden würden? https://developer.mozilla.org/en-US/docs/Web/API/History_API
Es scheint, dass es in mancher Hinsicht sauberer sein könnte, da man localStorage nicht verwenden müsste. Ich habe es allerdings noch nicht ausprobiert. Vielen Dank!
Ich bin mir nicht sicher, ob ich mit den Zielen dieses Codes übereinstimme, aber es ist trotzdem eine schöne Art, Leuten die Router-Hooks vorzustellen. Gut gemacht.