Heim >Web-Frontend >js-Tutorial >Was ist der Diff-Algorithmus in React? Strategie und Implementierung des Diff-Algorithmus
Der Inhalt dieses Artikels befasst sich mit der Frage, was der Diff-Algorithmus in React ist. Die Strategie und Implementierung des Diff-Algorithmus haben einen gewissen Referenzwert. Freunde in Not können sich darauf beziehen.
Traditioneller Diff: Der Diff-Algorithmus ist der Differenzsuchalgorithmus; für die HTML-DOM-Struktur ist er der Unterschied Suche nach Baumalgorithmus; die zeitliche Komplexität der Berechnung der Differenz zwischen zwei Bäumen ist offensichtlich zu teuer und es ist für React unmöglich, diesen traditionellen Algorithmus zu übernehmen; 🎜>
React Diff:Wie bereits erwähnt, nutzt React die virtuelle DOM-Technologie, um das reale DOM abzubilden, also die Differenzsuche von React Der Diff-Algorithmus dient im Wesentlichen dem Vergleich zweier JavaScript-Objektunterschiede.
basiert auf drei Strategien:
Zwei Komponenten mit derselben Klasse erzeugen ähnliche Baumstrukturen, und zwei Komponenten mit unterschiedlichen Klassen erzeugen unterschiedliche Baumstrukturen (Komponentenunterschied)
Eine Gruppe untergeordneter Knoten auf derselben Ebene kann durch eine eindeutige ID unterschieden werden. (Element Diff)
Strategiediagramm zur Optimierung des React Diff-Algorithmus:
React Die Aktualisierungsphase bestimmt den ReactElement-Typ und führt verschiedene Vorgänge aus. Zu den ReactElement-Typen gehören drei Typen: Text, Dom und Komponenten.
Die Aktualisierungsverarbeitungsmethode von Jeder Elementtyp:
Das Aktualisieren des Textknotens ist sehr einfach. Aktualisieren Sie einfach die Kopie direkt.
Die Aktualisierung der Grundelemente des Browsers gliedert sich in zwei Teile:
Die Aktualisierung von untergeordneten Knoten dient hauptsächlich dazu, die Differenzobjekte zu finden. Beim Auffinden der Differenzobjekte verwenden wir auch die obige „shouldUpdateReact“-Komponente, um zu beurteilen, ob sie direkt aktualisiert werden kann Rufen Sie die Aktualisierung des untergeordneten Knotens auf, wodurch das Differenzobjekt ebenfalls rekursiv gefunden wird. Das Löschen früherer Objekte oder das Hinzufügen neuer Objekte kann nicht direkt aktualisiert werden. Betreiben Sie dann das DOM-Element (Position ändern, löschen, hinzufügen usw.) entsprechend dem Differenzobjekt.
1. Wenn der Texttyp aktualisiert wird
ReactDOMTextComponent.prototype.receiveComponent(nextText, transaction) { //与之前保存的字符串比较 if (nextText !== this._currentElement) { this._currentElement = nextText; var nextStringText = '' + nextText; if (nextStringText !== this._stringText) { this._stringText = nextStringText; var commentNodes = this.getHostNode(); // 替换文本元素 DOMChildrenOperations.replaceDelimitedText( commentNodes[0], commentNodes[1], nextStringText ); } } }
2. Für benutzerdefinierte Komponentenelemente:
class Tab extends Component { constructor(props) { super(props); this.state = { index: 1, } } shouldComponentUpdate() { .... } render() { return ( <p> </p><p>item1</p> <p>item1</p> ) } }
Was eine Komponente ist, kann man sagen ist nur ein Verpackungscontainer einer HTML-Struktur und hat die Fähigkeit, den Status dieser HTML-Struktur zu verwalten.
Zum Beispiel ist die oben erwähnte Tab-Komponente: ihr wesentlicher Inhalt Die von der Renderfunktion zurückgegebene HTML-Struktur und die sogenannte Tab-Klasse sind der Verpackungscontainer dieser HTML-Struktur (kann als Verpackungsbox verstanden werden).
Wie Sie sehen können Im Diagramm des React-Rendering-Mechanismus wird die benutzerdefinierte Komponente schließlich mit der React Diff-Optimierungsstrategie 1 kombiniert (Zwei Komponenten verschiedener Klassen haben unterschiedliche Strukturen)
ReactDOMComponent.prototype.receiveComponent = function(nextElement, transaction, context) { var prevElement = this._currentElement; this._currentElement = nextElement; this.updateComponent(transaction, prevElement, nextElement, context); } ReactDOMComponent.prototype.updateComponent = function(transaction, prevElement, nextElement, context) { //需要单独的更新属性 this._updateDOMProperties(lastProps, nextProps, transaction, isCustomComponentTag); //再更新子节点 this._updateDOMChildren( lastProps, nextProps, transaction, context ); // ...... }
Dabei wird der Diff-Algorithmus intern in der _updateDOMChildren-Methode aufgerufen.
_updateChildren: function(nextNestedChildrenElements, transaction, context) { var prevChildren = this._renderedChildren; var removedNodes = {}; var mountImages = []; // 获取新的子元素数组 var nextChildren = this._reconcilerUpdateChildren( prevChildren, nextNestedChildrenElements, mountImages, removedNodes, transaction, context ); if (!nextChildren && !prevChildren) { return; } var updates = null; var name; var nextIndex = 0; var lastIndex = 0; var nextMountIndex = 0; var lastPlacedNode = null; for (name in nextChildren) { if (!nextChildren.hasOwnProperty(name)) { continue; } var prevChild = prevChildren && prevChildren[name]; var nextChild = nextChildren[name]; if (prevChild === nextChild) { // 同一个引用,说明是使用的同一个component,所以我们需要做移动的操作 // 移动已有的子节点 // NOTICE:这里根据nextIndex, lastIndex决定是否移动 updates = enqueue( updates, this.moveChild(prevChild, lastPlacedNode, nextIndex, lastIndex) ); // 更新lastIndex lastIndex = Math.max(prevChild._mountIndex, lastIndex); // 更新component的.mountIndex属性 prevChild._mountIndex = nextIndex; } else { if (prevChild) { // 更新lastIndex lastIndex = Math.max(prevChild._mountIndex, lastIndex); } // 添加新的子节点在指定的位置上 updates = enqueue( updates, this._mountChildAtIndex( nextChild, mountImages[nextMountIndex], lastPlacedNode, nextIndex, transaction, context ) ); nextMountIndex++; } // 更新nextIndex nextIndex++; lastPlacedNode = ReactReconciler.getHostNode(nextChild); } // 移除掉不存在的旧子节点,和旧子节点和新子节点不同的旧子节点 for (name in removedNodes) { if (removedNodes.hasOwnProperty(name)) { updates = enqueue( updates, this._unmountChild(prevChildren[name], removedNodes[name]) ); } } }Entwicklungsvorschläge basierend auf Diff
, achten Sie darauf, die DOM-Struktur stabil zu halten, dh die DOM-Struktur so wenig wie möglich dynamisch zu manipulieren, insbesondere mobil Operationen.
Achten Sie auf die Verwendung von ShouldComponentUpdate(), um unnötige Aktualisierungen von Komponenten zu reduzieren.
Ähnliche Strukturen sollten so weit wie möglich in Komponenten gekapselt werden, was nicht nur die Codemenge reduziert, sondern auch den Leistungsverbrauch von Komponentenunterschieden verringert.
Basierend auf Elementdiff:
Versuchen Sie bei Listenstrukturen, so etwas wie zu minimieren Das Hinzufügen des letzten Knotens an den Kopf der Liste wirkt sich in gewissem Maße auf die Renderleistung von React aus, wenn die Anzahl der Knoten zu groß ist oder die Aktualisierungsvorgänge zu häufig sind.
Das obige ist der detaillierte Inhalt vonWas ist der Diff-Algorithmus in React? Strategie und Implementierung des Diff-Algorithmus. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!