Eine Aufzeichnung der Fallstricke des Lebenszyklus von WeChat-Applet-Komponenten

Eine Aufzeichnung der Fallstricke des Lebenszyklus von WeChat-Applet-Komponenten

Der Komponentenlebenszyklus ist normalerweise der Anfang unserer Geschäftslogik.

Wenn das Geschäftsszenario komplex ist und der Komponentenlebenszyklus nicht wie erwartet verläuft,

Dies kann zu einigen seltsamen Geschäftsfehlern führen, die äußerst schwer zu reproduzieren und zu beheben sind.

Angehängte Komponente Lebenszyklus-Ausführungszeiten

Nach allgemeinem Verständnis gilt mit Ausnahme des Lebenszyklus von Verschieben/Anzeigen/Ausblenden, der mehrfach ausgeführt werden kann,

Genau genommen sollte der mit dem Laden von Komponenten verbundene Lebenszyklus (z. B. Erstellen, Anhängen, Bereitstellen usw.) für jede Komponenteninstanz nur einmal ausgeführt werden. Aber ist das wirklich der Fall?

Hintergrund

Die Entdeckung dieses Problems geht auf das Fehlerprotokoll unseres Miniprogramms zurück.

Ich habe viele Fehlermeldungen erhalten, wie „Eigenschaft kann nicht neu definiert werden: isComponent.“

Ursachenanalyse

Über den Variablennamen können wir zurückverfolgen, wie wir ihn im Code definiert haben:

Komponente({
 Lebensdauern:
 beigefügt() {
 Objekt.defineProperty(diese, 'isComponent', {
 aufzählbar: wahr,
 get() { return true },
 });
 },
 },
});

Es ist leicht zu verstehen, dass die Ursache dieses Fehlers der Versuch ist, eine nicht konfigurierbare Eigenschaft eines Objekts neu zu definieren.

Einzelheiten entnehmen Sie bitte der Beschreibung auf MDN.

Diese Definition steht aber im angehängten Lebenszyklus. Bedeutet das, dass der angehängte Lebenszyklus der Komponente zweimal ausgelöst wird?

Oh mein Gott, wie ist das möglich?

Ja, es ist so magisch!

Szenenwiederherstellung

Dieses Problem lässt sich nicht leicht reproduzieren. Durch kontinuierliche Vereinfachung und Entschlüsselung des Problems haben wir jedoch schließlich die Grundursache gefunden:

Bevor die Seite geladen wird, wird das Rendern der Unterkomponente durch Ändern des Status über setData ausgelöst und der angehängte Lebenszyklus der Unterkomponente wird zweimal ausgelöst.

Sie können dieses Szenario mit dem folgenden Code reproduzieren oder direkt auf den Codeausschnitt des Applets zugreifen.

Seite

// Seite.js
Seite({
 Daten: {
 showChild2: falsch,
 },
 beiKind1Angehängt() {
 this.setData({ showChild2: true });
 },
});

<!-- Seite.wxml -->
<child1 bind:attached="onChild1Attached"></child1>
<child2 wx:if="{{ showChild2 }}"></child2>

Unterkomponente 1

Wird zusammen mit der Seite gerendert und beim Anhängen wird die Seite benachrichtigt, den Status zu aktualisieren und Unterkomponente 2 über das TriggerEvent zu rendern.

//child1.js
Komponente({
 Lebensdauern:
 beigefügt() {
 this.triggerEvent('angehängt');
 },
 },
});

<!-- child1.wxml -->
<Ansicht>Kind1</Ansicht>

Unterkomponente 2

Der angehängte Lebenszyklus wurde zweimal ausgeführt, was zu einem Fehler führte.

//child2.js
Komponente({
 Lebensdauern:
 beigefügt() {
 Objekt.defineProperty(diese, 'isComponent', {
 aufzählbar: wahr,
 get() { return true },
 });
 },
 },
});
<!-- child2.wxml -->
<Ansicht>Kind2</Ansicht>

Ausführungszeit des Lebenszyklus einer bereiten Komponente

Die offizielle Dokumentation des Miniprogramms gibt die Ausführungsreihenfolge des Komponentenlebenszyklus nicht klar an, aber durch Ausdrucken des Protokolls können wir dies leicht herausfinden:

  • Während der Ladephase werden nacheinander folgende Schritte ausgeführt: erstellt -> angehängt -> bereit
  • Während der Deinstallationsphase werden die folgenden Vorgänge nacheinander ausgeführt:

Die Reihenfolge sollte also sein: erstellt -> angehängt -> bereit -> getrennt.

Aber ist das wirklich der Fall?

Hintergrund

Über einen gewissen Zeitraum hinweg wurde vom Kundenservice häufig berichtet, dass es in unserem Miniprogramm zu Datenstrings gekommen sei.

Beispiel: Die Live-Übertragung von Händler A stellt die Produkte von Händler B vor.

Ursachenanalyse

String-Daten kommen in mehreren Szenarien vor. Wenn man bedenkt, dass die Daten über Nachrichten an das Miniprogramm gesendet werden, liegt der Verdacht letztlich bei der WebSocket-Kommunikation.

Auf der Miniprogrammseite kapseln wir eine WebSocket-Kommunikationskomponente. Die Kernlogik lautet wie folgt:

// socket.js
Komponente({
 Lebensdauern:
 bereit() {
 dies.getSocketConfig().then(config => {
 this.ws = wx.connectSocket(Konfiguration);
 dies.ws.onMessage(msg => {
 const data = JSON.parse(msg.data);
 this.onReceiveMessage(Daten);
 });
 });
 },
 losgelöst() {
 dies.ws und dies.ws.close({});
 },
 },
 Methoden: {
 getSocketConfig() {
 // Socket-Verbindungskonfiguration vom Server anfordern return new Promise(() => {});
 },
 beiEmpfangsnachricht(Daten) {
 event.emit('Nachricht', Daten);
 },
 },
});

Einfach ausgedrückt: Wenn die Komponente bereit ist, wird eine WebSocket-Verbindung initialisiert und auf Nachrichten-Push gewartet. Anschließend wird die Verbindung in der getrennten Phase geschlossen.

Da es scheinbar kein Problem gibt, können wir aus den Ergebnissen nur Rückschlüsse auf eine Situation ziehen, die möglicherweise nicht mit dem gesunden Menschenverstand übereinstimmt.

Daten sind in falscher Reihenfolge -> WebSocket-Nachricht ist in falscher Reihenfolge -> WebSocket wird nicht richtig geschlossen -> Schließen ist falsch/Trennung wird nicht ausgeführt/Bereitschaft wird nach Trennung ausgeführt

Szenenwiederherstellung

Die eigentliche Geschäftslogik ist hierbei relativ komplex und kann daher nur durch vereinfachten Code überprüft werden.

Durch kontinuierliches Experimentieren fanden wir schließlich Folgendes heraus:

Es gibt keine klare Reihenfolge, in der die Komponenten „Bereit“ und „Getrennt“ ausgeführt werden.

Sie können dieses Szenario mit dem folgenden Code reproduzieren oder direkt auf den Codeausschnitt des Applets zugreifen.

Seite

// Seite.js
Seite({
 Daten: {
 showChild: wahr,
 },
 beim Laden() {
 dies.setData({ showChild: false });
 },
});

<!-- Seite.wxml -->
<child wx:if="{{ showChild }}" />

Komponenten

Wenn eine Komponente zerstört wird, wenn sie nicht bereit ist, wird „Detach“ zuerst synchron ausgeführt und „Ready“ dann asynchron.

//Kind.js
Komponente({
 Lebensdauern:
 erstellt() {
 console.log('erstellt');
 },
 beigefügt() {
 console.log('angehängt');
 },
 bereit() {
 console.log('bereit');
 },
 losgelöst() {
 console.log('getrennt');
 }
 },
});

expandieren

Auch wenn die Initialisierungsarbeit von der Bereitschaftsphase in die Anhängephase verschoben wird, ist es, solange ein asynchroner Vorgang vorliegt, immer noch möglich, dass die Trennung vor dem asynchronen Rückruf ausgeführt wird.

Vertrauen Sie deshalb bitte nicht vollständig auf den Zerstörungsvorgang während der Trennungsphase der Komponente.

Zusammenfassen

Dies ist das Ende dieses Artikels über die Fallstricke des Lebenszyklus von WeChat Mini-Programmkomponenten. Weitere relevante Inhalte zum Lebenszyklus von Mini-Programmkomponenten finden Sie in früheren Artikeln auf 123WORDPRESS.COM oder in den verwandten Artikeln weiter unten. Ich hoffe, Sie werden 123WORDPRESS.COM auch in Zukunft unterstützen!

Das könnte Sie auch interessieren:
  • Detaillierte Erläuterung der praktischen Fallstricke beim horizontalen Scrollen in der Scroll-Ansicht des WeChat-Applets und der Implementierung des Ausblendens der Bildlaufleiste
  • Das WeChat-Applet verwendet NPM-Unterstützung, um auf die Grube zu treten
  • Lösungen für die Fallstricke beim WeChat Mini-Programm-Slot
  • WeChat-Applet-Fallenfalle: Lösung des Problems, dass die Größe von tabBar.list[3].selectedIconPath 40 KB überschreitet
  • Die Fallstricke bei der Einführung von Vant-WeApp in das WeChat-Applet NPM
  • WeChat-Applet: benutzerdefinierter TabBar-Schrittübungsbericht
  • Echarts’ Fallstricke bei der Entwicklung von Taro WeChat-Applets
  • Detaillierte Erläuterung der Fallstricke des WeChat-Applet-Frameworks wepy (im Vergleich zu vue)
  • Kapitel zur Entwicklung von WeChat-Applets: Fallstricke

<<:  So zeigen Sie den Typ des gemounteten Dateisystems in Linux an

>>:  So ändern Sie das Kennwort von MySQL 5.1 und melden sich remote bei der MySQL-Datenbank an

Artikel empfehlen

MySQL 8.0-Installationstutorial unter Linux

Dieser Artikel beschreibt Ihnen, wie Sie MySQL 8....

Löschen von zwei Bildern mit derselben ID im Docker

Als ich heute einen Docker-Container erstellt hab...

JavaScript-Canvas zum Erzielen eines Spiegelbildeffekts

In diesem Artikel wird der spezifische Code für J...

Warum kann das in HTML eingebettete Video im MP4-Format nicht abgespielt werden?

Der folgende Code befindet sich in meiner test.htm...

So verwenden Sie vue.js zum Implementieren der Drag & Drop-Funktion

Vorwort Durch das Hinzufügen einer Drag & Dro...

VUE implementiert einen Beispielcode für das Spiel Flappy Bird

Flappy Bird ist ein sehr einfaches kleines Spiel,...

Tutorial zu HTML-Tabellen-Tags (13): Regeln für interne Rahmenstilattribute

Mit REGELN kann die Art der inneren Rahmen der Ta...

mysql5.6.zip-Format komprimierte Version Installations-Grafik-Tutorial

Vorwort: MySQL ist ein relationales Datenbankverw...

So verwenden Sie VirtualBox zum Simulieren eines Linux-Clusters

1. Richten Sie HOST auf dem Host-Macbook ein Im v...

Wartungsmethode für den Innodb-Systemtabellenbereich

Umweltbeschreibung: Es gibt eine laufende MySQL-U...

So wenden Sie TypeScript-Klassen in Vue-Projekten an

Inhaltsverzeichnis 1. Einleitung 2. Verwendung 1....

Beispiel einer Methode zur Fehlerbehebung beim Lösen von Nginx-Portkonflikten

Problembeschreibung Ein Spring + Angular-Projekt ...