La méthode diff de React peut être utilisée pour trouver la différence entre deux objets, dans le but de réutiliser les nœuds autant que possible ; l'algorithme diff est une implémentation spécifique de la réconciliation, et la réconciliation fait référence à la conversion d'une arborescence DOM virtuelle en un DOM réel. arbre Processus de fonctionnement minimal.
L'environnement d'exploitation de ce tutoriel : système Windows 10, React version 18.0.0, ordinateur Dell G3.
Quelle est la méthode diff en réaction ?
1. Le rôle de l'algorithme Diff
Le rendu du vrai DOM coûte très cher Parfois, nous modifions certaines données et le rendu directement dans le vrai DOM entraînera le redessinage et la réorganisation de l'ensemble de l'arborescence DOM. Nous espérons mettre à jour uniquement le petit morceau de DOM que nous avons modifié, pas l'intégralité du DOM. L'algorithme diff nous aide à y parvenir.
L'essence de l'algorithme diff est de trouver la différence entre deux objets, dans le but de réutiliser autant que possible les nœuds.
Remarque : L'objet mentionné ici fait en fait référence au dom virtuel (arbre dom virtuel) dans vue, c'est-à-dire à l'utilisation d'objets js pour représenter la structure dom dans la page.
Le processus d'opération minimum de conversion d'une arborescence DOM virtuelle en une arborescence DOM réelle est appelé réconciliation.
diff est l'implémentation spécifique de la réconciliation .
React utilise trois stratégies majeures pour réduire O(n3 ) la complexité est convertie en O (n) Complexité
(1)Stratégie 1 ( diff ) : Web là-bas Il existe très peu d'opérations de déplacement à plusieurs niveaux des nœuds DOM dans l'interface utilisateur et peuvent être ignorées.
(2) Stratégie 2 (component diff) : Deux composants avec la même classe génèrent une arborescence similaire, a Différentes catégories Les deux les composants génèrent différentes structures arborescentes.
(3) Stratégie trois (element diff) : Pour un groupe de nœuds enfants au même niveau, distinguez-les par des identifiants uniques.
sur l'arborescence DOM virtuelle Contrôle de niveau . (2) Comparez les arbres de manière hiérarchique. Deux arbres ne comparent que les nœuds
au même niveau . Si le nœud n'existe pas, le nœud et ses nœuds enfants seront complètement supprimés et ne seront plus comparés. (3) Un seul parcours est nécessaire pour terminer la comparaison de l'ensemble de l'arborescence DOM.
Si une opération multi-niveaux se produit sur un nœud DOM, que fera Diff ?
Réponse : Tree DIFF traverse chaque couche de l'arborescence. Si un composant n'existe plus, il sera détruit directement. Comme le montre la figure, le côté gauche est l'ancien attribut et le côté droit est le nouvel attribut. Le premier calque est le composant R, qui est exactement le même et ne changera pas. Le deuxième calque entre dans le composant DIFF et le même type. des composants continue d'être comparé. Il s'avère que le composant A n'existe pas, donc supprimez directement les composants A, B et C ; passez à la troisième couche et recréez les composants A, B et C ;
Comme le montre l'image ci-dessus, l'arbre entier avec A comme nœud racine sera recréé au lieu d'être déplacé. Par conséquent, il est officiellement recommandé de ne pas effectuer d'opérations à plusieurs niveaux sur les nœuds DOM. peut masquer et afficher des nœuds via CSS, et il ne s'agit pas vraiment de supprimer ou d'ajouter des nœuds DOM.
React propose trois stratégies pour comparer différents composants (1 ) Deux composants du même type, juste continuez à comparer l'arborescence Virtual DOM selon la stratégie d'origine (comparaison hiérarchique).
(2) Pour deux composants du même type, lorsque le composant A passe au composant B, le DOM virtuel peut ne pas changer du tout. Si vous le savez (le DOM virtuel ne change pas pendant le processus de transformation), vous pouvez. économisez beaucoup de temps de calcul. Par conséquent, les utilisateurs peuvent utiliser ShouldComponentUpdate() pour déterminer si un calcul de jugement est nécessaire. (3) Différents types de composants, jugent un composant (à changer) comme un composant sale, remplaçant ainsi tous les nœuds du composant entier. Remarque : Comme le montre la figure ci-dessus, Lorsque le composant D devient le composant G, même si les deux composants ont des structures similaires, Lorsque les nœuds sont au même niveau, diff Trois opérations de nœuds sont fournies : supprimer, insérer, déplacer. : Le composant C n'est pas dans l'ensemble (A, B) et doit à insérer Supprimer : (1) Le composant D est dans l'ensemble (A, B, D), mais le nœud de D a changé et ne peut pas être réutilisé et mis à jour, donc l'ancien D doit être supprimé et un nouveau créé. (2) Le composant D était auparavant dans l'ensemble (A,B,D), mais l'ensemble devient un nouvel ensemble (A,B), donc D doit être supprimé. Déplacement : Le composant D est déjà dans l'ensemble (A,B,C,D), et lorsque l'ensemble est mis à jour, D n'est pas mis à jour, mais la position change, comme dans le nouvel ensemble (A, D, B, C), D est en deuxième position, il n'est pas nécessaire de comparer le deuxième B de l'ancien ensemble avec le deuxième D du nouvel ensemble, et de supprimer le B dans le deuxième position, puis Insérez D à la deuxième position, mais (pour le même groupe de nœuds enfants au même niveau) ajoutez une clé unique pour le distinguer et déplacez-le simplement. Move Scénario 1 : Comment déplacer un nœud lorsque le même nœud existe dans le décors anciens et nouveaux mais dans des endroits différents
(1) B ne bouge pas, pas d'autres détails, mettre à jour l astIndex = 1 (2) Le nouvel ensemble obtient E et constate que l'ancien n'existe pas, donc il est créé à lastIndex = 1 E, update lastIndex=1 (3) Le nouvel ensemble obtient C, C ne bouge pas, update lastIndex=2 (4) Le nouvel ensemble obtient A, A se déplace, comme ci-dessus, mettez à jour lastIndex= 2 (5) Après avoir comparé le nouvel ensemble, parcourez l'ancien ensemble. On estime que le nouvel ensemble n'a pas d'éléments, mais que l'ancien ensemble a des éléments (comme D, le nouvel ensemble ne l'a pas, mais l'ancien ensemble l'a), D est trouvé, D est supprimé et le diff l’opération se termine. Code pour l'implémentation de l'algorithme Diff dans React : Basé sur l'arbre diff : Basé sur la différence des composants : Basé sur la différence d'élément : Apprentissage recommandé : "Tutoriel vidéo React"一旦React判断D和G是不用类型的组件,就不会比较两者的结构,而是直接删除组件D,重新创建组件G及其子节点。
Bien que lorsque les deux composants sont Lorsque différents types ont des structures similaires, l'exécution d'une analyse d'algorithme de différence affectera les performances. Cependant, après tout, il est rare que différents types de composants aient des arborescences DOM similaires dans le processus de développement réel. Il est donc difficile de prendre en compte ce facteur extrême. causer des problèmes majeurs dans le processus de développement actuel.
6、élément diff
_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])
);
}
}
}
3. Suggestions de développement basées sur Diff
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!