Maison > Article > interface Web > Qu'est-ce que l'algorithme Diff dans React ? Stratégie et implémentation de l'algorithme Diff
Le contenu de cet article porte sur ce qu'est l'algorithme Diff dans React ? La stratégie et la mise en œuvre de l'algorithme Diff ont une certaine valeur de référence. Les amis dans le besoin peuvent s'y référer, j'espère que cela vous sera utile.
Diff traditionnel : l'algorithme diff est l'algorithme de recherche de différence pour la structure HTML DOM, c'est la différence ; Algorithme de recherche d'arbre ; la complexité temporelle du calcul de la différence entre deux arbres est O(n^3), ce qui est évidemment trop coûteux et il est impossible pour React d'adopter cet algorithme traditionnel ; 🎜>
React Diff :Comme mentionné précédemment, React utilise la technologie DOM virtuel pour cartographier le DOM réel, c'est-à-dire la recherche de différence du React L'algorithme Diff consiste essentiellement à comparer deux JavaScripts. La recherche de différence d'objets
est basée sur trois stratégies :
Deux composants avec la même classe généreront des structures arborescentes similaires, et deux composants avec des classes différentes généreront des structures arborescentes différentes (diff de composant)
Pour un groupe de nœuds enfants de même niveau, ils peuvent être distingués par un identifiant unique. (élément diff)
Tableau de stratégie d'optimisation de l'algorithme React Diff :
React La phase de mise à jour déterminera le type ReactElement et effectuera différentes opérations ; les types ReactElement incluent trois types : texte, Dom et composants
La méthode de traitement de mise à jour de ; chaque type d'élément :
La mise à jour du nœud de texte est très simple, il suffit de mettre à jour la copie directement.
La mise à jour des éléments de base du navigateur est divisée en deux parties :
La mise à jour des nœuds enfants. La mise à jour des nœuds enfants consiste principalement à trouver les objets de différence, nous utiliserons également le ShouldUpdateReactComponent ci-dessus pour juger s'il peut être mis à jour directement. , ce sera récursif Appelez la mise à jour du nœud enfant, qui trouvera également l'objet différence de manière récursive. La suppression d'objets précédents ou l'ajout de nouveaux objets ne peuvent pas être directement mis à jour. Opérez ensuite l'élément DOM (changement de position, suppression, ajout, etc.) en fonction de l'objet de différence.
1. Si le type de texte est mis à jour
2. Pour les éléments de composant personnalisés :
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 ); } } }
Ce qu'il faut clarifier, c'est ce qu'est un composant. .On peut dire qu'un composant n'est qu'un morceau de Html Le conteneur d'emballage de la structure, et a la capacité de gérer le statut de cette structure Html
class Tab extends Component { constructor(props) { super(props); this.state = { index: 1, } } shouldComponentUpdate() { .... } render() { return ( <p> </p><p>item1</p> <p>item1</p> ) } }
Par exemple, le ci-dessus Composant Tab : son contenu essentiel est la structure Html renvoyée par la fonction de rendu, et ce que nous appelons la classe Tab est le conteneur d'emballage de cette structure Html (peut être compris comme une boîte d'emballage
3. Éléments de base :
L'algorithme diff est appelé dans la méthode this._updateDOMChildren.
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 ); // ...... }
_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]) ); } } }Basé sur les différences d'arbre :
Lors du développement de composants, faites attention à maintenir la structure DOM stable, c'est-à-dire à exploiter dynamiquement la structure DOM le moins possible, en particulier les opérations mobiles.
Basé sur la différence des composants
:Faites attention à utiliser ShouldComponentUpdate() pour réduire les mises à jour inutiles des composants.
Les structures similaires doivent être encapsulées dans des composants autant que possible, ce qui réduit non seulement la quantité de code, mais réduit également la consommation de performances des différences de composants.
Basé sur la différence d'élément :
Pour les structures de liste, essayez de minimiser quelque chose comme l'ajout du dernier L'opération de déplacement des nœuds en tête de liste affectera dans une certaine mesure les performances de rendu de React lorsque le nombre de nœuds est trop grand ou que les opérations de mise à jour sont trop fréquentes.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!