Front-End-Statusverwaltung (Teil 2)

Front-End-Statusverwaltung (Teil 2)

Vorwort:

Als Fortsetzung des vorherigen Artikels „Front-End-Statusverwaltung (Teil 1)“ hätte ich nicht erwartet, dass so viele Leser ihm so viel Aufmerksamkeit schenken würden. Vielen Dank an alle für Ihre Unterstützung und Vorschläge. Ich drücke nur meine persönliche Meinung und einige meiner eigenen Gedanken aus, die möglicherweise nicht umfassend genug sind. Das Beispiel der Verwendung von Vue ist nur ein Leitfaden und Vue hat auch ein hohes Maß an Aufmerksamkeit. Einige Freunde möchten neben Vuex noch andere Lösungen hören. Heute beginnen wir mit Redux und erweitern es schrittweise (genau wie der Titel).

1. Wiederholen

Als Mitglied der React Familie versucht Redux , einen vorhersehbaren Mechanismus zur Statusverwaltung für React Anwendungen bereitzustellen. Wie die meisten Lösungen zur Statusverwaltung ist auch die Idee von Redux ein Publish-Subscribe-Modell. Nehmen wir die Bibliothek als Beispiel, um Redux kurz zu verstehen.

Die grundlegenden Operationen von Redux sind ungefähr wie folgt:

  • Store (Bibliothekar)
  • State (Buch)
  • Action (Buchausleihliste)
  • store.dispatch (Ausleihliste übermitteln)
  • Reducer (Verpackungsbücher)
  • store.subscribe (Bücher erhalten)

1.1. Shop (Bibliothekar)

Store kann als Container betrachtet werden und in der gesamten Anwendung gibt es nur einen Store . Es ist, als ob Sie nur zum Bibliothekar gehen könnten, wenn Sie ein Buch ausleihen möchten.

importiere { createStore } von 'redux'
Konstantenspeicher = ErstelleSpeicher(Reducer);

1.2. Staat (Buch)

Der State kann nur über Action geändert werden (das heißt, Sie können Bücher nur ausleihen, indem Sie ein Ausleihformular übermitteln) und der Wert im State sollte nicht direkt geändert werden.

Verwenden Sie store.getState() um state abzurufen.

importiere { createStore } von 'redux'
const store = createStore(Reduzierer)
store.getState()

1.3. Aktion (Bücherausleihliste)

Und wenn Sie ein Buch ausleihen möchten? Selbstverständlich müssen Sie der Verwaltung eine Ausleihliste vorlegen. Dann kann der Benutzer nicht auf State zugreifen und nur über die Ansicht arbeiten (z. B. auf eine Schaltfläche klicken usw.). Das heißt, die State entspricht der View , sodass die Ansicht eine Action übermitteln muss, um State zu melden. (Das Einreichen der Ausleihliste beim Administrator führt zu einer Reihe weiterer Vorgänge)

Bei Action handelt es sich um ein benutzerdefiniertes Objekt, bei dem das Typattribut die vereinbarte auszuführende Operation ist.

const Aktion = {
    Typ: 'Klick',
    Info: 'Ausleihliste übermitteln'
}

1.4、store.dispatch (Ausleihliste übermitteln)

store.dispatch ist für View die einzige Möglichkeit, eine Aktion zu senden. Es akzeptiert ein Action (z. B. das Senden einer Ausleihliste) und gibt die Listeninformationen einfach an den Bibliothekar weiter, der dann anhand der Liste nach den entsprechenden Büchern sucht.

store.dispatch(Aktion)

1.5. Reducer (Verpackungsbücher)

Nachdem Store eine Action empfangen hat, muss er einen neuen Status zuweisen, damit sich die Ansicht ändert, und der Berechnungsprozess des neuen State wird vom Reducer abgeschlossen. (Nachdem Sie die Bestellung erhalten haben, packen Sie Ihre Bücher in Tüten usw.)

Reducer ist eine benutzerdefinierte Funktion, die Aktion und aktuellen State als Parameter akzeptiert und einen neuen Status zurückgibt.

const Reducer = (Status, Aktion) => {
    return `action.info: ${state}` // => Ausleihliste übermitteln: Traum der Roten Kammer}

store.subscribe (Bücher erhalten)
Sobald sich der Status ändert, hört store.subscribe() darauf und aktualisiert die Ansicht automatisch.

const abmelden = store.subscribe(() => {
  rendern() {
    //Aktualisiere die Ansicht 
  }
})
// Sie können sich auch abmelden (anhören)
abbestellen()

Zusammenfassung:

Ich glaube, dass Studierende, die gerade erst mit Redux in Berührung gekommen sind, Redux eher kompliziert finden werden, was auch mit seiner Idee zusammenhängt: Bei Redux soll alles sicher sein.

Obwohl es immer noch unmöglich ist, in Redux alles deterministisch zu machen (wie etwa Asynchronität) , sollte die Deterministik der meisten Teile garantiert sein, darunter:

  • Die Ansichtsdarstellung ist deterministisch
  • Der Wiederaufbau des Staates ist deterministisch

Warum wir das tun sollten, habe ich bereits im vorherigen Artikel erwähnt. Seine Bedeutung liegt in der Erleichterung des Anwendungstests, der Fehlerdiagnose und der Bug .

2. Zweck der staatlichen Verwaltung

Tatsächlich besteht das häufigste Szenario für die meisten Programmierer bei der Verwendung von Redux darin, von Seite A zu Seite B zurückzukehren und den Status von Seite B speichern zu müssen.

Wenn das Projekt nicht groß ist, würde die Verwendung Redux oder Vuex dann etwas groß erscheinen? Wir wissen, dass Vue keep-alive bereitstellt, damit wir die aktuelle Komponente zwischenspeichern können, wodurch das obige Szenario gelöst werden kann.

Aber leider gibt es in React kein keep-alive wie in Vue. Die in der Community übliche Lösung besteht darin, das Routing zu ändern. Diese Änderung ist jedoch zu invasiv für das Projekt und schwer zu warten. Darüber hinaus wird der Routing-Hook in react-router v5 ebenfalls gelöscht. Daher bietet es sich an, bei kleinen Projekten selbst eine Funktion zu kapseln. (Natürlich können Sie Redux verwenden, wenn Sie möchten, wir erkunden lediglich weitere Möglichkeiten)

Nehmen wir die Bibliothek als Beispiel. Jetzt gibt es ein Bibliotheksverwaltungssystem. Wenn Sie von der Listenseite (Liste) zur detail (Detail) springen, müssen Sie den Status der Listenseite speichern (z. B. den Status der Suchleiste usw.).

Angenommen, der von Ihnen verwendete Technologie-Stack ist ( react + antd ), schreiben Sie von Hand einen einfachen und groben Stack (der Kern besteht darin, context für die Datenübertragung zwischen Komponenten zu verwenden):

//KeepAlive.js
exportiere Standardfunktion keepAliveWrapper() {
  Rückgabefunktion keepAlive(WrappedComponent) {
    Rückgabeklasse KeepAlive erweitert WrappedComponent { // ps
      Konstruktor(Requisiten) {
        super(Requisiten)
        // mach was...
      }

      componentDidMount() {
        Konstante {
          keepAlive: { FelderWert },
        } = dieser.Kontext
        // mach was...
        super.componentDidMount()

      }

      rendern() {
        // mach was...
        return super.render()
      }
    }
  }
}

Deshalb müssen wir die ursprüngliche Komponente erben (// ps)

Wenn die herkömmliche Schreibmethode eine Klassenkomponente zurückgibt ( class KeepAlive extends React.Component ), handelt es sich im Wesentlichen um eine verschachtelte übergeordnete und untergeordnete Komponente. Der Lebenszyklus der übergeordneten und untergeordneten Komponenten wird der Reihe nach ausgeführt, sodass jedes Mal, wenn Sie zur Listenseite zurückkehren, um den Status abzurufen, diese zweimal gerendert wird. Dies liegt daran, dass die vom HOC zurückgegebene übergeordnete Komponente die Methode der ursprünglichen Komponente aufruft, was dazu führt, dass die Listenseite zweimal angefordert und zweimal gerendert wird.

Wenn HOC (High-Order Component) von der Originalkomponente erbt, werden zwei Lebenszyklen nicht abwechselnd ausgeführt, was dieses Problem gut löst.

// main.jsx-Stammkomponente importiere React von „react“

const appContext = React.createContext()

Klasse App erweitert React.Component {
    Konstruktor(Requisiten) {
        super(Requisiten)
        dieser.Zustand = {
          keepAlive: {}, // Objekt zwischenspeichern isCache: false, // Ob fieldsValue zwischengespeichert werden soll: {} // Formularwert zwischenspeichern }
    }
    componentDidMount() {
        // Initialisieren const keepAlive = {
          isCache: dieser.Zustand.isCache,
          umschalten: this.toggleCache.bind(this),
          FelderWert: dieser.Status.FelderWert,
        }
        dies.setState({ keepAlive })
    }
    // Hier ist eine Methode zum Löschen des Status, um Rendering-Warnungen zu verhindern (Sie können vor dem Rendern keine Felder festlegen ...)
    // Beispielsweise muss list1 => list1/detail => list2 den Sprung in den folgenden Rückruf einfügen und den Status löschen toggleCache(isCache = false, payload, callback) {
        const { fieldsValue = null } = Nutzlast
        const keepAlive = {
          istCache,
          FelderWert,
          umschalten: this.toggleCache.bind(this),
        }
        const fn = Typ des Rückrufs === 'Funktion' ? Rückruf() : void 0
        dies.setState(
          {
            am Leben bleiben,
          },
          () => {
            fn
          }
        )
    }
    rendern() {
        const { keepAlive } = dieser.Zustand
        <appContext.Provider-Wert={{ keepAlive }}>
            // Ihre Routen ...
        </appContext.Provider>
    }

}

Der Grund, warum wir context nicht direkt verwenden, sondern eine zusätzliche Ebene von keepAlive einkapseln, besteht darin, die Verarbeitung context zu vereinheitlichen. Durch die Verwendung der prägnanten Schreibmethode des Dekorators (@keepAlive) im Komponentenheader wissen Sie sofort, dass dies eine zwischengespeicherte Komponente ist (für einfaches Lesen und Warten).

// importiere React von „react“, wenn du es auf der Seite verwendest
importiere keepAlive von '../keepAlive'

// keepAlive muss am nächsten an der Originalkomponente platziert werden @keepAlive()
Klasse App erweitert React.Component {
    Konstruktor (Requisiten) {
        super(Requisiten)
        dieser.Zustand = {
            // etwas initialisieren …
        }
    }
    componentDidMount() {
        // tu etwas...
        wenn(dieser.Kontext.keepAlive.fieldsValue) {
            const { tableList } = this.context.keepAlive.fieldsValue
            console.log('Zwischengespeichert:',Tabellenliste) // Cache: ['1', '2']
        }
    }
    // Details anzeigen detail = () => {
        this.context.keepAlive.fieldsValue = {
            Tabellenliste: ['1', '2']
        }
        // springen...
    }
    // Wenn Sie über die Route der ersten Ebene springen müssen, z. B. list1 => list1/detail (die folgende Methode sollte auf der Detailseite stehen) => list2, müssen Sie die Warnung toList2 = () => { behandeln.
        this.context.keepAlive.toggle(false, {}, () => {
            // springen...
        })
    }
}

Im obigen Beispiel wird Dekorator-Schreiben verwendet. Um es einfach auszudrücken, müssen Sie das folgende babel konfigurieren, bevor Sie es verwenden können ~

npm install -D @babel/plugin-proposal-decorators

Konfigurieren Sie in jsconfig.json (erstellen Sie eine neue, falls sie noch nicht vorhanden ist):

{
    "Compileroptionen": {
        "experimentalDecorators": wahr
    },
    "ausschließen": [
        "Knotenmodule",
        "Entfernung"
    ]
}

In .babelrc konfigurieren:

{
    "Plugins": [
        "@babel/plugin-proposal-decorators",
        {
            "Legacy": wahr
        }
    ]
}

Die obige Methode ist für das gerade erwähnte Szenario besser geeignet (um von Seite A zu Seite B zurückzukehren, muss der Status von Seite B gespeichert werden). Manche Leute sagen, dass Sie genauso gut Redux oder Mobx verwenden könnten. Beim Überspringen von Routen müssen Sie den Status manuell löschen, um Warnungen zu vermeiden. . . Verschiedene Leute haben verschiedene Meinungen. Die Tatsache, dass Sie es selbst zusammengefasst haben, zeigt, dass Sie einige Nachforschungen dazu angestellt haben. Egal, wie einfach oder schwierig es ist, geht es beim Programmieren nicht um kontinuierliche Erforschung? Haha. Auch wenn das, was Sie schreiben, vielleicht nicht gut genug ist oder so, nehmen Sie Kritik einfach bescheiden an. Schließlich gibt es da draußen viele talentierte Menschen.

Zusammenfassen:

Dies ist das Ende dieses Artikels über Front-End-Statusverwaltung. Weitere Inhalte zur Front-End-Statusverwaltung finden Sie in früheren Artikeln auf 123WORDPRESS.COM oder in den folgenden verwandten Artikeln. Ich hoffe, Sie werden 123WORDPRESS.COM auch in Zukunft unterstützen!

Rückblick auf den vorherigen Artikel: Eine kurze Diskussion über die Front-End-Statusverwaltung (Teil 1)

Das könnte Sie auch interessieren:
  • Front-End-Statusverwaltung (Teil 1)
  • Detailliertes Beispiel für die Statusverwaltung der Hilfsfunktion der Vue-Frontend-Entwicklung

<<:  Nginx tp3.2.3 404 Problemlösung

>>:  HTML-Tabellen-Markup-Tutorial (18): Tabellenkopf

Artikel empfehlen

Der Unterschied zwischen schreibgeschützt und deaktiviert

Um es zusammenzufassen: „Nur lesen“ ist nur für Ei...

Vue implementiert Drag-Fortschrittsbalken

In diesem Artikelbeispiel wird der spezifische Co...

Detaillierte Erläuterung des Ausführungsprozesses der JavaScript-Engine V8

Inhaltsverzeichnis 1. V8-Quelle 2. V8-Serviceziel...

Praxis der Linux-Datei- und Benutzerverwaltung

1. Zeigen Sie die Dateien oder Verzeichnisse im V...

Detaillierte Analyse der Unterschiede zwischen break und last in Nginx

Lassen Sie uns zunächst über den Unterschied spre...

So verwenden Sie SVG-Symbole in WeChat-Applets

SVG wurde in den letzten Jahren aufgrund seiner v...

MySQL-Transaktions-Tutorial Yii2.0 Händler-Auszahlungsfunktion

Vorwort Ich bin ein PHP-Programmierer, der als Pr...

Eine kurze Diskussion darüber, ob CSS-Animationen durch JS blockiert werden

Der Animationsteil von CSS wird von JS blockiert,...