So verwenden Sie Typescript zum Kapseln von lokalem Speicher

So verwenden Sie Typescript zum Kapseln von lokalem Speicher

Vorwort

Lokaler Speicher ist eine Technologie, die häufig in der Front-End-Entwicklung verwendet wird, aber die offizielle API ist unpraktisch in der Anwendung und für einige Funktionen, wie z. B. das Festlegen der Ablaufzeit, stehen uns keine entsprechenden APIs zur Verfügung. Dieser Artikel soll kein Wissen zum Konzept der lokalen Speicherung vermitteln, sondern zielt darauf ab, eine nützliche lokale Speicherklasse mithilfe von Typescript zu kapseln.

Szenarien für die Verwendung lokaler Speicher

  • Token-Speicherung nach Benutzeranmeldung
  • Speicherung von Benutzerinformationen
  • Kommunikation zwischen verschiedenen Seiten
  • Persistenz des Projektstatusmanagements, wie z. B. Redux-Persistenz, Vuex-Persistenz usw.
  • Leistungsoptimierung usw.
  • ...

Probleme bei der Nutzung

  • Die offizielle API ist nicht sehr benutzerfreundlich (zu lang) und alle Daten werden in Form von Zeichenfolgen gespeichert. Für den Zugriff ist eine Datentypkonvertierung erforderlich.
    • localStorage.setItem(Schlüssel, Wert)
    • ...
  • Ablaufzeit kann nicht festgelegt werden
  • Da sie im Klartext gespeichert sind, können einige relativ private Informationen von Benutzern problemlos im Browser angezeigt werden.
  • Projekte gleichen Ursprungs teilen sich lokalen Speicherplatz, was zu Datenverwirrung führen kann

Lösung

Die Lösungen für die oben genannten Probleme sind in einer Klasse gekapselt und werden den Benutzern über eine einfache Schnittstelle zum direkten Aufruf zur Verfügung gestellt. Die Klasse kapselt die folgende Funktionalität:

  • Datentypkonvertierung
  • Ablaufzeit
  • Datenverschlüsselung
  • Einheitliche Namenskonvention

Funktionalität

 // Speicher.ts

enum Speichertyp {
  l = "lokaler Speicher",
  s = "Sitzungsspeicher"
}

Klasse MyStorage {
  Speicher: Speicher

  Konstruktor(Typ: Speichertyp) {
    this.storage = Typ === StorageType.l ? window.localStorage : window.sessionStorage
  }

  Satz(
    Schlüssel: Zeichenfolge,
    Wert: beliebig
  ) {
    const Daten = JSON.stringify(Wert)
    this.storage.setItem(Schlüssel, Daten)
  }

  get(Schlüssel: Zeichenfolge) {
    Konstantwert = this.storage.getItem(Schlüssel)
    wenn (Wert) {
      gibt JSON.parse(Wert) zurück
  }

  löschen(Schlüssel: Zeichenfolge) {
    this.storage.removeItem(Schlüssel)
  }

  klar() {
    dies.storage.clear()
  }
}

const LStorage = neuer MyStorage(StorageType.l)
const SStorage = neuer MyStorage(StorageType.s)

exportiere { LStorage, SStorage }

Der obige Code implementiert einfach die Grundfunktionen des lokalen Speichers und führt die Datentypkonvertierungsoperation während des Zugriffs intern durch. Die Verwendung ist wie folgt:

 importiere { LStorage, SStorage } aus './storage'

...

LStorage.set('Daten', { Name: 'zhangsan' })
LStorage.get('Daten') // { Name: 'zhangsan' }

Ablaufzeit hinzufügen

Die Idee hinter dem Festlegen der Ablaufzeit ist: Beim Festlegen wird den Daten das Feld „expires“ hinzugefügt, um die Datenspeicherzeit aufzuzeichnen. Beim Abrufen werden die abgerufenen „expires“ mit der aktuellen Zeit verglichen. Wenn die aktuelle Zeit größer als „expires“ ist, bedeutet dies, dass die Zeit abgelaufen ist. Zu diesem Zeitpunkt wird der Datensatz gelöscht und null zurückgegeben. Der Typ „expires“ kann ein Boolescher Typ oder ein Zahlentyp sein. Der Standardwert ist „false“, d. h., es wird keine Ablaufzeit festgelegt. Wenn der Benutzer den Wert auf „true“ setzt, beträgt die Standardablaufzeit 1 Jahr. Wenn der Benutzer den Wert auf einen bestimmten Wert setzt, ist die Ablaufzeit der vom Benutzer festgelegte Wert. Der Code wird wie folgt implementiert:

 Schnittstelle IStoredItem {
  Wert: beliebig
  läuft ab?: Nummer
}
...
Satz(
    Schlüssel: Zeichenfolge,
    Wert: beliebig,
    läuft ab: Boolesch | Zahl = falsch,
  ) {
    const Quelle: IStoredItem = { Wert: null }
    wenn (abläuft) {
    // Die Standardablaufzeit beträgt 1 Jahr und kann entsprechend den tatsächlichen Bedingungen angepasst werden. source.expires =
        neues Date().getTime() +
        (läuft ab === wahr? 1000 * 60 * 60 * 24 * 365: läuft ab)
    }
    Quelle.Wert = Wert
    const data = JSON.stringify(Quelle)
    this.storage.setItem(Schlüssel, Daten)
  }
  
  get(Schlüssel: Zeichenfolge) {
    Konstantwert = this.storage.getItem(Schlüssel)
    wenn (Wert) {
      const-Quelle: IStoredItem = JSON.parse(Wert)
      const läuft ab = Quelle.läuft ab
      const jetzt = neues Date().getTime()
      wenn (läuft ab && jetzt > läuft ab) {
        this.delete(Schlüssel)
        return null
      }

      returniere Quelle.Wert
    }
  }

Datenverschlüsselung hinzufügen

Das Paket crypto-js wird zur Verschlüsselung verwendet. Die beiden privaten Methoden encrypt und decrypt sind in der Klasse gekapselt, um die Datenverschlüsselung und -entschlüsselung zu handhaben. Natürlich können Benutzer auch über das Verschlüsselungsfeld festlegen, ob Daten verschlüsselt werden sollen. Der Standardwert ist true, was bedeutet, dass die Verschlüsselung standardmäßig aktiviert ist. Darüber hinaus kann die aktuelle Umgebung über process.env.NODE_ENV abgerufen werden. Wenn es sich um eine Entwicklungsumgebung handelt, wird sie nicht verschlüsselt, um die Entwicklung und das Debuggen zu erleichtern. Der Code wird wie folgt implementiert:

 CryptoJS aus „crypto-js“ importieren

const SECRET_KEY = "nkldsx@#45#VDss9"
const IS_DEV = process.env.NODE_ENV === 'Entwicklung'
...
Klasse MyStorage {
  ...
  
  private Verschlüsselung(Daten: Zeichenfolge) {
    gibt CryptoJS.AES.encrypt(data, SECRET_KEY).toString() zurück
  }

  private Entschlüsselung(Daten: Zeichenfolge) {
    const bytes = CryptoJS.AES.decrypt(Daten, SECRET_KEY)
    gibt bytes.toString zurück(CryptoJS.enc.Utf8)
  }
  
  Satz(
    Schlüssel: Zeichenfolge,
    Wert: beliebig,
    läuft ab: Boolesch | Zahl = falsch,
    Verschlüsselung = wahr
  ) {
    const Quelle: IStoredItem = { Wert: null }
    wenn (abläuft) {
      Quelle.läuft ab =
        neues Date().getTime() +
        (läuft ab === wahr? 1000 * 60 * 60 * 24 * 365: läuft ab)
    }
    Quelle.Wert = Wert
    const data = JSON.stringify(Quelle)
    this.storage.setItem(Schlüssel, IS_DEV ? Daten : Verschlüsselung ? this.encrypt(Daten) : Daten
    )
  }
  
  get(Schlüssel: Zeichenfolge, Verschlüsselung = true) {
    Konstantwert = this.storage.getItem(Schlüssel)
    wenn (Wert) {
      const-Quelle: IStoredItem = JSON.parse(Wert)
      const läuft ab = Quelle.läuft ab
      const jetzt = neues Date().getTime()
      wenn (läuft ab && jetzt > läuft ab) {
        this.delete(Schlüssel)
        return null
      }

      return IS_DEV
        ? Quellwert
        : Verschlüsselung
        ? dies.entschlüsseln(Quelle.Wert)
        : Quelle.Wert
    }
  }
  
}

Namenskonventionen hinzufügen

Sie können die Benennung standardisieren, indem Sie vor dem Schlüssel ein Präfix hinzufügen, z. B. einen zusammengesetzten Schlüssel vom Typ Projektname_Versionsnummer_Schlüssel. Diese Benennungskonvention kann frei festgelegt werden, entweder durch eine Konstante oder durch Verketten von Name und Version in package.json. Der Code lautet wie folgt:

 const konfiguration = erfordern('../../paket.json')

const PREFIX = Konfigurationsname + '_' + Konfigurationsversion + '_'

...
Klasse MyStorage {

  // Schlüssel synthetisieren
  privater Syntheseschlüssel (Schlüssel: Zeichenfolge) {
    return PREFIX + Schlüssel
  }
  
  ...
  
 Satz(
    Schlüssel: Zeichenfolge,
    Wert: beliebig,
    läuft ab: Boolesch | Zahl = falsch,
    Verschlüsselung = wahr
  ) {
    ...
    dieses.storage.setItem(
      this.synthesisKey(Schlüssel),
      IS_DEV? Daten: Verschlüsselung? this.encrypt(Daten): Daten
    )
  }
  
  get(Schlüssel: Zeichenfolge, Verschlüsselung = true) {
    Konstantwert = this.storage.getItem(this.synthesisKey(Schlüssel))
    ...
  }

}

Vollständiger Code

 CryptoJS aus „crypto-js“ importieren
const konfiguration = erfordern('../../paket.json')

enum Speichertyp {
  l = "lokaler Speicher",
  s = "Sitzungsspeicher"
}

Schnittstelle IStoredItem {
  Wert: beliebig
  läuft ab?: Nummer
}

const SECRET_KEY = "nkldsx@#45#VDss9"
const PREFIX = Konfigurationsname + '_' + Konfigurationsversion + '_'
const IS_DEV = process.env.NODE_ENV === 'Entwicklung'

Klasse MyStorage {
  Speicher: Speicher

  Konstruktor(Typ: Speichertyp) {
    dieser.Speicher =
      Typ === StorageType.l ? Fenster.localStorage : Fenster.sessionStorage
  }

  private Verschlüsselung(Daten: Zeichenfolge) {
    gibt CryptoJS.AES.encrypt(data, SECRET_KEY).toString() zurück
  }

  private Entschlüsselung(Daten: Zeichenfolge) {
    const bytes = CryptoJS.AES.decrypt(Daten, SECRET_KEY)
    gibt bytes.toString zurück(CryptoJS.enc.Utf8)
  }

  privater Syntheseschlüssel (Schlüssel: Zeichenfolge) {
    return PREFIX + Schlüssel
  }

  Satz(
    Schlüssel: Zeichenfolge,
    Wert: beliebig,
    läuft ab: Boolesch | Zahl = falsch,
    Verschlüsselung = wahr
  ) {
    const Quelle: IStoredItem = { Wert: null }
    wenn (abläuft) {
      Quelle.läuft ab =
        neues Date().getTime() +
        (läuft ab === wahr? 1000 * 60 * 60 * 24 * 365 : läuft ab)
    }
    Quelle.Wert = Wert
    const data = JSON.stringify(Quelle)
    dieses.storage.setItem(
      this.synthesisKey(Schlüssel),
      IS_DEV? Daten: Verschlüsselung? this.encrypt(Daten): Daten
    )
  }

  get(Schlüssel: Zeichenfolge, Verschlüsselung = true) {
    Konstantwert = this.storage.getItem(this.synthesisKey(Schlüssel))
    wenn (Wert) {
      const-Quelle: IStoredItem = JSON.parse(Wert)
      const läuft ab = Quelle.läuft ab
      const jetzt = neues Date().getTime()
      wenn (läuft ab && jetzt > läuft ab) {
        this.delete(Schlüssel)
        return null
      }

      return IS_DEV
        ? Quellwert
        : Verschlüsselung
        ? dies.entschlüsseln(Quelle.Wert)
        : Quelle.Wert
    }
  }

  löschen(Schlüssel: Zeichenfolge) {
    this.storage.removeItem(this.synthesisKey(Schlüssel))
  }

  klar() {
    dies.storage.clear()
  }
}

const LStorage = neuer MyStorage(StorageType.l)
const SStorage = neuer MyStorage(StorageType.s)

exportiere { LStorage, SStorage }

Zusammenfassen

Dies ist das Ende dieses Artikels zur Verwendung von Typescript zur Kapselung des lokalen Speichers. Weitere relevante Inhalte zur Kapselung des lokalen Speichers mit Typescript finden Sie in früheren Artikeln auf 123WORDPRESS.COM oder in den folgenden verwandten Artikeln. Ich hoffe, dass jeder 123WORDPRESS.COM in Zukunft unterstützen wird!

<<:  Empfehlen Sie einen coolen blinkenden Alarmknopf

>>:  Beispielcode zum Ändern des Textstils der Eingabeaufforderung in HTML

Artikel empfehlen

Einige Kenntnisse über die absolute und relative Positionierung von Seitenelementen

Ab heute werde ich regelmäßig kleine Wissenspunkte...

Implementierungsprinzip der MySQL MyISAM-Standardspeicher-Engine

Standardmäßig generiert die MyISAM-Tabelle drei D...

Benutzerdefinierte optionale Zeitkalenderkomponente von Vue

In diesem Artikelbeispiel wird der spezifische Co...

jQuery klickt auf den Liebeseffekt

In diesem Artikel wird der spezifische Code des j...

MySQL-Platzhalter (erweiterte SQL-Filterung)

Inhaltsverzeichnis Lassen Sie uns zunächst kurz P...

Beispielcode des Vue-Symbolselektors

Quelle: http://www.ruoyi.vip/ Vue von „vue“ impor...

So aktivieren Sie die MySQL-Remoteverbindung auf einem Linux-Server

Vorwort Lernen Sie MySQL, um frühere Nicht-MK-Dat...

Ein super detailliertes Vue-Router Schritt-für-Schritt-Tutorial

Inhaltsverzeichnis 1. Router-Ansicht 2. Router-Ve...

Beispiele für die Verwendung von MySQL-Abdeckungsindizes

Was ist ein Deckungsindex? Das Erstellen eines In...

Einführung in die MySQL-Gesamtarchitektur

Die Gesamtarchitektur von MySQL ist in die Server...

Eine detaillierte Analyse und Verarbeitung von MySQL-Alarmen

Vor kurzem hat ein Dienst einen Alarm ausgelöst, ...