Seitenaktualisierungen sind eine Sache. Manchmal aktualisieren wir eine Seite, wenn wir denken, dass sie nicht reagiert, oder wir glauben, dass neue Inhalte verfügbar sind. Manchmal sind wir einfach sauer auf die verdammte Seite und aktualisieren sie wütend, um ihr zu zeigen, dass wir unzufrieden sind.
Wäre es nicht schön zu wissen, wann ein Benutzer die Seite aktualisiert? Nicht nur das, sondern wie oft? Diese Daten können uns helfen, nach einer bestimmten Anzahl von Neuladungen ein bestimmtes Verhalten auszulösen.
Eine Sportseite ist ein gutes Beispiel. Wenn ich den Spielstand eines Spiels überprüfen möchte, das gerade läuft, aber die Spielstände nicht live aktualisiert werden, dann neige ich vielleicht dazu, mehrmals zu aktualisieren.
Unser Ziel ist es, Benutzern diese Gewohnheit abzutrainieren. Wir nutzen unsere Seitenaktualisierungszählungsfähigkeiten, um die Leute wissen zu lassen, dass Aktualisierungen unnötig sind, dank Echtzeit-Spielstandaktualisierungen. Und wenn sie mehr als dreimal neu laden? Wir werfen sie aus ihrer Sitzung. Das wird ihnen zeigen.
Hier ist eine einfache Demo dieses Konzepts.
Lassen Sie uns es gemeinsam nachbauen. Aber bevor wir loslegen, müssen wir ein paar Fragen beantworten, bevor wir mit dem Codieren beginnen.
- Wie können wir die Anzahl der Neuladungen der Seite durch den Benutzer speichern? Wir brauchen einen Ort, um die Anzahl der Neuladungen der Seite durch den Benutzer (
reloadCount) zu speichern. Dieser Ort muss diesen Wert zwischen den Neuladungen beibehalten –localStoragescheint eine gute Lösung zu sein. - Wie erkennen wir, ob der Benutzer die Seite neu geladen hat oder nur nach ein paar Stunden zurückgekehrt ist? Wenn wir
reloadCountinlocalStoragespeichern, wird der Wert zwischen den Neuladungen beibehalten, aber er wird behalten, bis wir ihn programmatisch entfernen oder den Browser-Speicher löschen. Das bedeutet, dass die Seite, wenn wir nach ein paar Stunden zurückkehren, sich immer noch an den letztenreloadCounterinnern wird und nach der ersten Aktualisierung möglicherweise ohne Vorwarnung abgemeldet wird. Wir wollen das vermeiden und dem Benutzer erlauben, die Seite jedes Mal zweimal neu zu laden, wenn er nach einer bestimmten Zeit zurückkehrt. Der letzte Satz enthält die Antwort auf die Frage. Wir müssen die Zeit speichern, zu der der Benutzer die Seite verlassen hat, und dann, wenn die Seite erneut geladen wird, prüfen, wann dies geschah. Wenn dieser Zeitraum nicht lang genug war, aktivieren wir die Logik zur Zählung von Neuladungen. - Woher wissen wir, wann der Benutzer die Seite verlässt? Um diese Zeit zu speichern, verwenden wir das
beforeunloadFensterereignis und speichern diesen Wert inlocalStorage.
Okay, jetzt, da wir die Antworten haben, tauchen wir in den Code ein.
Schritt 1: Wir müssen die Zeit der letzten Neuladung speichern
Wir speichern die Zeit der letzten Neuladung mit einem beforeunload Fensterereignis. Wir brauchen zwei Dinge: (1) einen Ereignislistener, der auf das Ereignis hört und die entsprechende Methode auslöst, und (2) unsere beforeUnloadHandler Methode.
Zuerst erstellen wir eine Funktion namens initializeReloadCount, die unseren Ereignislistener mit der addEventListener Methode des window-Objekts setzt.
function initializeReloadCount() {
window.addEventListener("beforeunload", beforeUnloadHandler)
}
Dann erstellen wir eine zweite Methode, die aufgerufen wird, bevor wir die Seite verlassen. Diese Methode speichert die Zeit, zu der die Aktualisierung stattfindet, in localStorage.
function beforeUnloadHandler() {
localStorage.setItem("lastUnloadAt", Math.floor(Date.now() / 1000))
window.removeEventListener("beforeunload", beforeUnloadHandler);
}
Schritt 2: Wir brauchen eine Möglichkeit, die Anzahl der Neuladungen zu verarbeiten und zu speichern
Jetzt, da wir die Zeit kennen, zu der die Seite zuletzt geschlossen wurde, können wir fortfahren und die Logik implementieren, die für die Erkennung und Zählung verantwortlich ist, wie oft die Seite neu geladen wurde. Wir brauchen eine Variable, um unseren reloadCount zu speichern und uns mitzuteilen, wie oft der Benutzer die Seite neu geladen hat.
let reloadCount = null
Dann müssen wir in unserer initializeReloadCount Funktion zwei Dinge tun:
- Prüfen, ob wir bereits einen
reloadCount-Wert in unseremlocalStoragegespeichert haben, und wenn ja, diesen Wert abrufen und in unseremreloadCountspeichern. Wenn der Wert nicht existiert, bedeutet dies, dass der Benutzer die Seite zum ersten Mal geladen hat (oder sie zumindest nicht neu geladen hat). In diesem Fall setzen wirreloadCountauf Null und speichern diesen Wert inlocalStorage. - Erkennen, ob die Seite neu geladen wurde oder der Benutzer nach einer längeren Zeitspanne zurückgekehrt ist. Hier brauchen wir unseren
lastUnloadAt-Wert. Um zu erkennen, ob die Seite tatsächlich neu geladen wurde, müssen wir die Zeit, zu der die Seite geladen wird (die aktuelle Zeit), mit demlastUnloadAt-Wert vergleichen. Wenn diese beiden Ereignisse innerhalb, sagen wir, fünf Sekunden (was völlig willkürlich ist) stattgefunden haben, bedeutet dies, dass der Benutzer die Seite neu geladen hat und wir die Logik zur Neuladungszählung ausführen sollten. Wenn die Zeitspanne zwischen diesen beiden Ereignissen länger ist, setzen wir denreloadCount-Wert zurück.
Damit erstellen wir eine neue Funktion namens checkReload und behalten diese Logik dort.
function checkReload() {
if (localStorage.getItem("reloadCount")) {
reloadCount = parseInt(localStorage.getItem("reloadCount"))
} else {
reloadCount = 0
localStorage.setItem("reloadCount", reloadCount)
}
if (
Math.floor(Date.now() / 1000) - localStorage.getItem("lastUnloadAt") <
5
) {
onReloadDetected()
} else {
reloadCount = 0;
localStorage.setItem("reloadCount", reloadCount)
}
}
Die letzte Funktion, die wir in diesem Schritt benötigen, ist eine Methode, die dafür verantwortlich ist, was passiert, wenn wir bestätigen, dass der Benutzer die Seite neu geladen hat. Wir nennen diese Funktion onReloadDetected, und darin erhöhen wir den Wert von reloadCount. Wenn der Benutzer die Seite zum dritten Mal aktualisiert hat, schlagen wir zu und rufen unsere logout-Logik auf.
function onReloadDetected() {
reloadCount = reloadCount + 1
localStorage.setItem("reloadCount", reloadCount)
if (reloadCount === 3) {
logout()
}
}
Schritt 3: „Lieber Benutzer, warum hast du nicht zugehört?!“
In diesem Schritt implementieren wir die Logik, die für die Situation verantwortlich ist, wenn der Benutzer die Seite so oft neu lädt, dass er unser Dreifach-Limit überschreitet, trotz unserer deutlichen Warnungen, damit aufzuhören.
Wenn das passiert, rufen wir unsere API auf, um den Benutzer abzumelden, und bereinigen dann alle Eigenschaften, die mit der Logik zur Zählung von Neuladungen zusammenhängen. Dies ermöglicht es dem Benutzer, zurückzukehren und eine saubere Aufzeichnung der Neuladungen zu haben. Wir können den Benutzer auch irgendwohin umleiten, wie z. B. zur Anmeldeseite. (Aber wäre es nicht lustig, ihn stattdessen hierhin zu schicken?)
function logout(params) {
// logout API call
resetReloadCount()
}
function resetReloadCount() {
window.removeEventListener("beforeunload", beforeUnloadHandler)
localStorage.removeItem("lastUnloadAt")
localStorage.removeItem("reloadCount");
}
Bonus: Lassen Sie uns es mit Vue neu betrachten!
Jetzt, da wir die Logik implementiert haben, sehen wir uns an, wie wir diese Logik auf eine Vue-Seite übertragen können, basierend auf diesem Beispiel.
Zuerst müssen wir alle unsere Variablen in die data unseres Komponenten verschieben, wo alle reaktiven Eigenschaften leben.
export default {
data() {
return {
reloadCount: 0,
warningMessages: [...]
}
},
Dann verschieben wir alle unsere Funktionen in methods.
// ...
methods: {
beforeUnloadHandler() {...},
checkReload() {...},
logout() {...},
onReloadDetected() {...},
resetReloadCount() {...},
initializeReloadCount() {...}
}
// ...
Da wir Vue und sein Reaktivitätssystem verwenden, können wir alle direkten DOM-Manipulationen (z. B. document.getElementById("app").innerHTML) fallen lassen und uns auf unsere warningMessages Daten-Eigenschaft verlassen. Um die richtige Warnmeldung anzuzeigen, müssen wir eine berechnete Eigenschaft hinzufügen, die sich jedes Mal neu berechnet, wenn unser reloadCount geändert wird, damit wir einen String aus unseren warningMessages zurückgeben können.
computed: {
warningMessage() {
return this.warningMessages[this.reloadCount];
}
},
Dann können wir auf unsere berechnete Eigenschaft direkt in der Vorlage der Komponente zugreifen.
<template>
<div id="app">
<p>{{ warningMessage }}</p>
</div>
</template>
Das Letzte, was wir tun müssen, ist einen geeigneten Platz zu finden, um die Logik zur Verhinderung von Neuladungen zu aktivieren. Vue bietet Komponenten-Lifecycle Hooks, die genau das sind, was wir brauchen, insbesondere den created Hook. Lassen Sie uns das einfügen.
// ...
created() {
this.initializeReloadCount();
},
// ...
Schön.
Zusammenfassung
Und da ist es, die Logik, die prüft und zählt, wie oft eine Seite aktualisiert wurde. Ich hoffe, Sie haben die Fahrt genossen und finden diese Lösung nützlich oder zumindest inspirierend, um etwas Besseres zu tun. 🙂
Gute Anleitung.
Es scheint, als könnten Sie viel Ärger sparen, indem Sie einfach sessionStorage anstelle von faking mit localStorage verwenden.
Ich glaube nicht, dass sessionStorage funktionieren wird, da bei jeder Neuladung des Benutzers eine neue Sitzung generiert wird. Bitte korrigieren Sie mich, wenn ich falsch liege.
sessionStorage überlebt Seitenneuladungen. Aus den MDN-Dokumenten:
Und das Problem mit Neuladungen ist……? Sicherlich gleicht Ihr zusätzlicher Code, der für alle bereitgestellt wird, die meisten oder alle Einsparungen aus?
Stimme zu. Ich bin mir nicht sicher, warum es mich interessieren sollte, ob der Benutzer zweimal oder 200 Mal aktualisiert.
Das Problem mit erzwungenen Neuladungen ist, dass sie möglicherweise immer wieder eine „Ausführung“ im Backend auslösen.
Daher wird empfohlen, bei einer Neuladung über sinnvolle Reaktionen auf den Benutzer und wahrscheinlich das Backend nachzudenken.
Natürlich hängt alles von der Anwendung und der Architektur ab.
Ich glaube nicht, dass das der Weg ist, die Gewohnheit zu brechen. Der Benutzer lädt aus irgendeinem Grund neu. Wenn er anfängt, mehrmals neu zu laden, bedeutet das, dass er das Gefühl hat, dass die Benutzeroberfläche sich nicht aktualisiert oder auf seine Aktionen nicht reagiert. Ein Neuladen ist eine einfache Lösung für die meisten JS-bezogenen Fehler, bei denen eine Seite in einem kaputten Zustand endet. Meiner Meinung nach sollten wir zeigen, dass die Seite reaktionsfähig ist (nein, nicht im Sinne der Bildschirmgröße des Browsers, sondern anders reaktionsfähig). Zeigen Sie ihm, dass wir Dinge überprüfen, auch wenn sich dadurch der Anwendungsstatus selbst nicht ändert.
Und natürlich sollten Sie, wenn die Neuladungen ein Problem für Sie sind, bereits nach Helfern suchen, die die Ladezeit und die Serverkosten reduzieren – Abfrageleistung, schnelle Caching-Schicht oder sogar horizontale Skalierbarkeit, wenn Ihr Server so kurz vor der Überlastung steht, dass selbst mehrere aufeinanderfolgende Neuladungen ihn beeinträchtigen würden.
Schließlich würde die Aussage an den Benutzer „Sie dürfen die Seite nicht neu laden“ seine Gewohnheiten nicht ändern. Möglicherweise verärgern Sie ihn sogar. Wie gesagt, er tut das aus einem Grund und in den meisten Fällen würde er sich berechtigt fühlen, dies zu tun. Wenn ich eine solche Warnung sehen würde, insbesondere nachdem ich erlebt habe, dass die Anwendung abgestürzt ist, Verbindungsprobleme aufgetreten sind oder die Benutzeroberfläche nicht aktualisiert wurde, würde ich lieber wütend auflegen und etwas finden, das einfach funktioniert.
Ich würde sagen, das Einzige, was solche Mechanismen rechtfertigen würde, ist DOS- und DDOS-Schutz, aber das ist bereits in Dingen wie Cloudflare integriert.
Das war vielleicht nur zu Demozwecken, aber Benutzer für „unangemessenes Verhalten“ rauszuschmeißen, ist wahrscheinlich nie die richtige Lösung. Ganz zu schweigen davon, dass es wahrscheinlich diskriminierend ist, da technisch weniger versierte Personen weitaus wahrscheinlicher betroffen sind.
Die ideale Lösung hier scheint eine Benutzeroberfläche und eine Benutzererfahrung zu sein, die den Benutzer implizit dazu ermutigt, nicht neu zu laden. Dies könnte bedeuten, dass „zuletzt aktualisiert um 13:22 Uhr“ mit einer sich aktualisierenden Anzeige angezeigt wird.
Ich stimme vollkommen zu. Das ist extrem feindselig gegenüber dem Benutzer, und obwohl es als technisches Beispiel dient, wäre es viel schöner, wenn es durch etwas anderes ersetzt würde; vielleicht eine Anleitung für WebSockets, um die Seite zu aktualisieren und sie live zu halten? Strg+R abfangen, um den Inhalt neu zu laden, ohne die gesamte Seite zu aktualisieren? Demonstrieren, wie man zurückkehrende Benutzer begrüßt und ihnen zeigt, was seit ihrer letzten Sitzung neu ist?
Die Verwendung von Vue.js dafür scheint mir übertrieben.
Hier ist ein Codepen mit dem obigen Code, der in einem einfachen HTML enthalten ist, mit einigen kleineren Anpassungen.
Grüße
„Und wenn sie mehr als dreimal neu laden? Wir werfen sie aus ihrer Sitzung. Das wird ihnen zeigen.“
Ich hoffe, das war wirklich ein Witz? Bitte.