Maison interface Web js tutoriel Résumé des compétences d'utilisation de l'algorithme de comparaison

Résumé des compétences d'utilisation de l'algorithme de comparaison

May 11, 2018 pm 01:35 PM
diff 使用技巧 总结

Cette fois, je vais vous apporter un résumé des techniques d'utilisation de l'algorithme diff. Quelles sont les précautions lors de l'utilisation de l'algorithme diff. Voici des cas pratiques, jetons un coup d'oeil.

Dom virtuel

L'algorithme de diff doit d'abord clarifier le concept selon lequel l'objet de diff est le dom virtuel, et la mise à jour du dom réel est le résultat de l'algorithme de diff

Classe de base Vnode

 constructor (
  。。。
 ) {
  this.tag = tag
  this.data = data
  this.children = children
  this.text = text
  this.elm = elm
  this.ns = undefined
  this.context = context
  this.fnContext = undefined
  this.fnOptions = undefined
  this.fnScopeId = undefined
  this.key = data && data.key
  this.componentOptions = componentOptions
  this.componentInstance = undefined
  this.parent = undefined
  this.raw = false
  this.isStatic = false
  this.isRootInsert = true
  this.isComment = false
  this.isCloned = false
  this.isOnce = false
  this.asyncFactory = asyncFactory
  this.asyncMeta = undefined
  this.isAsyncPlaceholder = false
 }
Copier après la connexion

Cette partie du code vise principalement à mieux comprendre la signification de l'attribut du diff spécifique dans l'algorithme diff. Bien sûr, il peut également être modifié. Mieux comprendre l'instance de vnode

Le processus global

La fonction principale est la fonction patch

  • Jugement isUndef (qu'il soit indéfini ou nul)

  • // montage vide (probablement en tant que composant), créez un nouvel élément racinecreateElm(vnode, insertVnodeQueue) Ici vous pouvez constater que les nœuds créés ne sont pas insérés un par un, mais mis dans une file d'attente pour unifier le traitement par lots

  • Fonction principale sameVnode

function sameVnode (a, b) {
 return (
  a.key === b.key && (
   (
    a.tag === b.tag &&
    a.isComment === b.isComment &&
    isDef(a.data) === isDef(b.data) &&
    sameInputType(a, b)
   ) || (
    isTrue(a.isAsyncPlaceholder) &&
    a.asyncFactory === b.asyncFactory &&
    isUndef(b.asyncFactory.error)
   )
  )
 )
}
Copier après la connexion

Voici une fonction de comparaison externe qui compare directement les clés de deux nœuds, la balise (tag), la comparaison des données (notez que les données ici font référence à VNodeData), en cas d'entrée, comparez directement le type.

export interface VNodeData {
 key?: string | number;
 slot?: string;
 scopedSlots?: { [key: string]: ScopedSlot };
 ref?: string;
 tag?: string;
 staticClass?: string;
 class?: any;
 staticStyle?: { [key: string]: any };
 style?: object[] | object;
 props?: { [key: string]: any };
 attrs?: { [key: string]: any };
 domProps?: { [key: string]: any };
 hook?: { [key: string]: Function };
 on?: { [key: string]: Function | Function[] };
 nativeOn?: { [key: string]: Function | Function[] };
 transition?: object;
 show?: boolean;
 inlineTemplate?: {
  render: Function;
  staticRenderFns: Function[];
 };
 directives?: VNodeDirective[];
 keepAlive?: boolean;
}
Copier après la connexion

Cela confirmera si les deux nœuds méritent une comparaison plus approfondie, sinon ils seront remplacés directement

Le processus de remplacement est principalement une fonction createElm et l'autre est la destruction de oldVNode

// destroy old node
    if (isDef(parentElm)) {
     removeVnodes(parentElm, [oldVnode], 0, 0)
    } else if (isDef(oldVnode.tag)) {
     invokeDestroyHook(oldVnode)
    }
Copier après la connexion

Le processus d'insertion consiste simplement à déterminer le type du nœud et à appeler

createComponent (il déterminera s'il y a des enfants puis l'appellera de manière récursive)

createComment

createTextNode

Utilisez la fonction d'insertion après la création

Après cela, vous devez utiliser la fonction hydrate pour mapper le dom virtuel et le dom réel

function insert (parent, elm, ref) {
  if (isDef(parent)) {
   if (isDef(ref)) {
    if (ref.parentNode === parent) {
     nodeOps.insertBefore(parent, elm, ref)
    }
   } else {
    nodeOps.appendChild(parent, elm)
   }
  }
 }
Copier après la connexion

Fonction principale

 function patchVnode (oldVnode, vnode, insertedVnodeQueue, removeOnly) {
  if (oldVnode === vnode) {
   return
  }
  const elm = vnode.elm = oldVnode.elm
  if (isTrue(oldVnode.isAsyncPlaceholder)) {
   if (isDef(vnode.asyncFactory.resolved)) {
    hydrate(oldVnode.elm, vnode, insertedVnodeQueue)
   } else {
    vnode.isAsyncPlaceholder = true
   }
   return
  }
  if (isTrue(vnode.isStatic) &&
   isTrue(oldVnode.isStatic) &&
   vnode.key === oldVnode.key &&
   (isTrue(vnode.isCloned) || isTrue(vnode.isOnce))
  ) {
   vnode.componentInstance = oldVnode.componentInstance
   return
  }
  let i
  const data = vnode.data
  if (isDef(data) && isDef(i = data.hook) && isDef(i = i.prepatch)) {
   i(oldVnode, vnode)
  }
  const oldCh = oldVnode.children
  const ch = vnode.children
  if (isDef(data) && isPatchable(vnode)) {
   for (i = 0; i < cbs.update.length; ++i) cbs.update[i](oldVnode, vnode)
   if (isDef(i = data.hook) && isDef(i = i.update)) i(oldVnode, vnode)
  }
  if (isUndef(vnode.text)) {
   if (isDef(oldCh) && isDef(ch)) {
    if (oldCh !== ch) updateChildren(elm, oldCh, ch, insertedVnodeQueue, removeOnly)
   } else if (isDef(ch)) {
    if (isDef(oldVnode.text)) nodeOps.setTextContent(elm, &#39;&#39;)
    addVnodes(elm, null, ch, 0, ch.length - 1, insertedVnodeQueue)
   } else if (isDef(oldCh)) {
    removeVnodes(elm, oldCh, 0, oldCh.length - 1)
   } else if (isDef(oldVnode.text)) {
    nodeOps.setTextContent(elm, &#39;&#39;)
   }
  } else if (oldVnode.text !== vnode.text) {
   nodeOps.setTextContent(elm, vnode.text)
  }
  if (isDef(data)) {
   if (isDef(i = data.hook) && isDef(i = i.postpatch)) i(oldVnode, vnode)
  }
 }
Copier après la connexion

const el = vnode.el = oldVnode.el C'est une étape très importante Laissez vnode.el se référer au réel actuel. dom. Lorsque el est modifié, vnode.el changera de manière synchrone.

  1. Comparez si les deux références sont cohérentes

  2. Je ne sais pas ce que fait asyncFactory après ça, donc je ne peux pas comprendre cette comparaison

  3. Clé de comparaison de nœud statique, aucun nouveau rendu ne sera effectué après le même, copiez directement l'instance de composant (une fois que la commande prend effet ici)

  4. Si vnode est un nœud de texte Ou commentaire nœud, mais lorsque vnode.text != oldVnode.text, il vous suffit de mettre à jour le contenu texte de vnode.elm

  5. Comparaison des enfants

  • Si seulement oldVnode a des nœuds enfants, supprimez ces nœuds

  • Si seulement vnode a des nœuds enfants, puis créez ces nœuds enfants. Si oldVnode est un nœud de texte, définissez le texte de vnode.elm sur une chaîne vide

  • Si les deux sont disponibles. , updateChildren sera mis à jour.

  • Si ni oldVnode ni vnode n'ont de nœuds enfants, mais que oldVnode est un nœud de texte ou un nœud d'annotation, définissez le texte de vnode.elm. à une chaîne vide

updateChildren

L'accent de cette partie est toujours sur l'ensemble de l'algorithme

Quatre premiers pointeurs, oldStart, oldEnd, newStart, newEnd, deux tableaux, oldVnode, Vnode .

function updateChildren (parentElm, oldCh, newCh, insertedVnodeQueue, removeOnly) {
  let oldStartIdx = 0
  let newStartIdx = 0
  let oldEndIdx = oldCh.length - 1
  let oldStartVnode = oldCh[0]
  let oldEndVnode = oldCh[oldEndIdx]
  let newEndIdx = newCh.length - 1
  let newStartVnode = newCh[0]
  let newEndVnode = newCh[newEndIdx]
  let oldKeyToIdx, idxInOld, vnodeToMove, refElm
  while (oldStartIdx <= oldEndIdx && newStartIdx <= newEndIdx) {
   if (isUndef(oldStartVnode)) {
    oldStartVnode = oldCh[++oldStartIdx] // Vnode has been moved left
   } else if (isUndef(oldEndVnode)) {
    oldEndVnode = oldCh[--oldEndIdx]
   } else if (sameVnode(oldStartVnode, newStartVnode)) {
    patchVnode(oldStartVnode, newStartVnode, insertedVnodeQueue)
    oldStartVnode = oldCh[++oldStartIdx]
    newStartVnode = newCh[++newStartIdx]
   } else if (sameVnode(oldEndVnode, newEndVnode)) {
    patchVnode(oldEndVnode, newEndVnode, insertedVnodeQueue)
    oldEndVnode = oldCh[--oldEndIdx]
    newEndVnode = newCh[--newEndIdx]
   } else if (sameVnode(oldStartVnode, newEndVnode)) { // Vnode moved right
    patchVnode(oldStartVnode, newEndVnode, insertedVnodeQueue)
    canMove && nodeOps.insertBefore(parentElm, oldStartVnode.elm, nodeOps.nextSibling(oldEndVnode.elm))
    oldStartVnode = oldCh[++oldStartIdx]
    newEndVnode = newCh[--newEndIdx]
   } else if (sameVnode(oldEndVnode, newStartVnode)) { // Vnode moved left
    patchVnode(oldEndVnode, newStartVnode, insertedVnodeQueue)
    canMove && nodeOps.insertBefore(parentElm, oldEndVnode.elm, oldStartVnode.elm)
    oldEndVnode = oldCh[--oldEndIdx]
    newStartVnode = newCh[++newStartIdx]
   } else {
    if (isUndef(oldKeyToIdx)) oldKeyToIdx = createKeyToOldIdx(oldCh, oldStartIdx, oldEndIdx)
    idxInOld = isDef(newStartVnode.key)
     ? oldKeyToIdx[newStartVnode.key]
     : findIdxInOld(newStartVnode, oldCh, oldStartIdx, oldEndIdx)
    if (isUndef(idxInOld)) { // New element
     createElm(newStartVnode, insertedVnodeQueue, parentElm, oldStartVnode.elm, false, newCh, newStartIdx)
    } else {
     vnodeToMove = oldCh[idxInOld]
     if (sameVnode(vnodeToMove, newStartVnode)) {
      patchVnode(vnodeToMove, newStartVnode, insertedVnodeQueue)
      oldCh[idxInOld] = undefined
      canMove && nodeOps.insertBefore(parentElm, vnodeToMove.elm, oldStartVnode.elm)
     } else {
      // same key but different element. treat as new element
      createElm(newStartVnode, insertedVnodeQueue, parentElm, oldStartVnode.elm, false, newCh, newStartIdx)
     }
    }
    newStartVnode = newCh[++newStartIdx]
   }
  }
  if (oldStartIdx > oldEndIdx) {
   refElm = isUndef(newCh[newEndIdx + 1]) ? null : newCh[newEndIdx + 1].elm
   addVnodes(parentElm, refElm, newCh, newStartIdx, newEndIdx, insertedVnodeQueue)
  } else if (newStartIdx > newEndIdx) {
   removeVnodes(parentElm, oldCh, oldStartIdx, oldEndIdx)
  }
 }
Copier après la connexion

Plusieurs situations et traitement d'une comparaison de boucle (les ++ suivants -- font tous référence au ++ de l'index --) La comparaison est le nœud nœud comparé L'abréviation n'est pas rigoureuse et. la comparaison est utilisée La fonction sameVnode n'est pas vraiment congruente

La condition pour que la boucle entière ne se termine pas oldStartIdx <= oldEndIdx && newStartIdx <= newEndIdx

  1. oldStart === newStart, oldStart++ newEnd --

  2. oldEnd === newStart, oldEnd est inséré au début de la file d'attente oldEnd-- newStart++

  3. Toutes les situations restantes sont traitées de cette façon. Pour faire simple, il y a deux processus après le traitement, newStart++

    .
  • newStart在old中发现一样的那么将这个移动到oldStart前

  • 没有发现一样的那么创建一个放到oldStart之前

循环结束后并没有完成

还有一段判断才算完

if (oldStartIdx > oldEndIdx) {
   refElm = isUndef(newCh[newEndIdx + 1]) ? null : newCh[newEndIdx + 1].elm
   addVnodes(parentElm, refElm, newCh, newStartIdx, newEndIdx, insertedVnodeQueue)
  } else if (newStartIdx > newEndIdx) {
   removeVnodes(parentElm, oldCh, oldStartIdx, oldEndIdx)
  }

相信看了本文案例你已经掌握了方法,更多精彩请关注php中文网其它相关文章!

推荐阅读:

axios发送post请求提交图片表单步骤详解

axios+post方法提交formdata步骤详解

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!

Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn

Outils d'IA chauds

Undresser.AI Undress

Undresser.AI Undress

Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover

AI Clothes Remover

Outil d'IA en ligne pour supprimer les vêtements des photos.

Undress AI Tool

Undress AI Tool

Images de déshabillage gratuites

Clothoff.io

Clothoff.io

Dissolvant de vêtements AI

AI Hentai Generator

AI Hentai Generator

Générez AI Hentai gratuitement.

Article chaud

R.E.P.O. Crystals d'énergie expliqués et ce qu'ils font (cristal jaune)
1 Il y a quelques mois By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Meilleurs paramètres graphiques
1 Il y a quelques mois By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Comment réparer l'audio si vous n'entendez personne
1 Il y a quelques mois By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Commandes de chat et comment les utiliser
1 Il y a quelques mois By 尊渡假赌尊渡假赌尊渡假赌

Outils chauds

Bloc-notes++7.3.1

Bloc-notes++7.3.1

Éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise

SublimeText3 version chinoise

Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1

Envoyer Studio 13.0.1

Puissant environnement de développement intégré PHP

Dreamweaver CS6

Dreamweaver CS6

Outils de développement Web visuel

SublimeText3 version Mac

SublimeText3 version Mac

Logiciel d'édition de code au niveau de Dieu (SublimeText3)

Résumer l'utilisation de la fonction system() dans le système Linux Résumer l'utilisation de la fonction system() dans le système Linux Feb 23, 2024 pm 06:45 PM

Résumé de la fonction system() sous Linux Dans le système Linux, la fonction system() est une fonction très couramment utilisée, qui permet d'exécuter des commandes en ligne de commande. Cet article présentera la fonction system() en détail et fournira quelques exemples de code spécifiques. 1. Utilisation de base de la fonction system(). La déclaration de la fonction system() est la suivante : intsystem(constchar*command) où le paramètre de commande est un caractère.

Comment utiliser le langage Go pour l'analyse financière quantitative ? Comment utiliser le langage Go pour l'analyse financière quantitative ? Jun 11, 2023 am 08:51 AM

Dans le domaine de la finance moderne, avec l'essor de la science des données et de la technologie de l'intelligence artificielle, la finance quantitative est progressivement devenue une direction de plus en plus importante. En tant que langage de programmation typé statiquement capable de traiter efficacement les données et de déployer des systèmes distribués, le langage Go a progressivement attiré l'attention dans le domaine de la finance quantitative. Cet article présentera comment utiliser le langage Go pour effectuer une analyse financière quantitative. Le contenu spécifique est le suivant : Obtention de données financières Tout d'abord, nous devons obtenir des données financières. Les capacités de programmation réseau du langage Go sont très puissantes et peuvent être utilisées pour obtenir diverses données financières. Comparer

Comment utiliser le langage Go pour le data mining ? Comment utiliser le langage Go pour le data mining ? Jun 10, 2023 am 08:39 AM

Avec l'essor du Big Data et de l'exploration de données, de plus en plus de langages de programmation ont commencé à prendre en charge les fonctions d'exploration de données. En tant que langage de programmation rapide, sûr et efficace, le langage Go peut également être utilisé pour l'exploration de données. Alors, comment utiliser le langage Go pour le data mining ? Voici quelques étapes et techniques importantes. Acquisition de données Tout d'abord, vous devez obtenir les données. Cela peut être réalisé par divers moyens, tels que l'exploration d'informations sur des pages Web, l'utilisation d'API pour obtenir des données, la lecture de données à partir de bases de données, etc. Le langage Go est livré avec un HTTP riche

Comment utiliser PHP pour développer des fonctions simples d'optimisation SEO Comment utiliser PHP pour développer des fonctions simples d'optimisation SEO Sep 20, 2023 pm 04:18 PM

Comment utiliser PHP pour développer des fonctions simples d'optimisation du référencement Le référencement (SearchEngineOptimization), ou optimisation des moteurs de recherche, fait référence à l'amélioration du classement du site Web dans les moteurs de recherche en améliorant la structure et le contenu du site Web, obtenant ainsi plus de trafic organique. Dans le développement de sites Web, comment utiliser PHP pour mettre en œuvre des fonctions simples d’optimisation SEO ? Cet article présentera quelques techniques d'optimisation SEO couramment utilisées et des exemples de code spécifiques pour aider les développeurs à mettre en œuvre l'optimisation SEO dans les projets PHP. 1. Utilisation conviviale

Comment utiliser nginx pour empêcher les hotlinking Comment utiliser nginx pour empêcher les hotlinking Jun 11, 2023 pm 01:25 PM

Avec la popularité d’Internet, de plus en plus de sites Web proposent des fonctions de liens externes vers des images, des vidéos et d’autres ressources. Cependant, cette fonction de lien externe est facile à voler. Le hotlinking signifie que d'autres sites Web utilisent des images, des vidéos et d'autres ressources sur votre site Web pour afficher directement ces ressources sur leur propre site Web via l'adresse de référence au lieu de les télécharger sur leur propre serveur. De cette façon, les sites Web hotlink peuvent utiliser gratuitement les ressources de trafic et de bande passante de votre site Web, ce qui gaspille des ressources et affecte la vitesse du site Web. Pour résoudre ce problème, Nginx peut être utilisé pour empêcher les hotlinking. Nginx est

Comment écrire l'algorithme d'arbre couvrant minimum en utilisant C# Comment écrire l'algorithme d'arbre couvrant minimum en utilisant C# Sep 19, 2023 pm 01:55 PM

Comment utiliser C# pour écrire l'algorithme d'arbre couvrant minimum L'algorithme d'arbre couvrant minimum est un algorithme important de la théorie des graphes, qui est utilisé pour résoudre le problème de connectivité des graphiques. En informatique, un arbre couvrant minimum fait référence à un arbre couvrant d'un graphe connecté dans lequel la somme des poids de toutes les arêtes de l'arbre couvrant est la plus petite. Cet article explique comment utiliser C# pour écrire l'algorithme d'arbre couvrant minimum et fournit des exemples de code spécifiques. Tout d’abord, nous devons définir une structure de données graphique pour représenter le problème. En C#, vous pouvez utiliser une matrice de contiguïté pour représenter un graphique. Une matrice de contiguïté est un tableau à deux dimensions dans lequel chaque élément représente

Remplacer svn diff par vimdiff : un outil pour comparer le code Remplacer svn diff par vimdiff : un outil pour comparer le code Jan 09, 2024 pm 07:54 PM

Sous Linux, il est très difficile d'utiliser directement la commande svndiff pour visualiser les modifications de code, j'ai donc cherché une meilleure solution sur Internet, qui consiste à utiliser vimdiff comme outil de visualisation de code pour svndiff, en particulier pour les personnes habituées à utiliser vim. C'est très pratique. Lorsque vous utilisez la commande svndiff pour comparer les modifications d'un certain fichier, par exemple, si vous exécutez la commande suivante : $svndiff-r4420ngx_http_limit_req_module.c, la commande suivante sera en fait envoyée au programme diff par défaut : -u-Lngx_http_limit_req_module.c (révision4420)-Lngx_

Solution simple : un guide complet sur les techniques d'utilisation de la source miroir pip Solution simple : un guide complet sur les techniques d'utilisation de la source miroir pip Jan 16, 2024 am 10:31 AM

Solution en un clic : maîtrisez rapidement les compétences d'utilisation de la source miroir pip Introduction : pip est l'outil de gestion de packages le plus couramment utilisé pour Python, qui peut facilement installer, mettre à niveau et gérer les packages Python. Cependant, pour des raisons bien connues, l'utilisation de la source miroir par défaut pour télécharger le package d'installation est plus lente. Afin de résoudre ce problème, nous devons utiliser une source miroir nationale. Cet article expliquera comment maîtriser rapidement les compétences d'utilisation de la source miroir pip et fournira des exemples de code spécifiques. Avant de commencer, comprenez le concept de source miroir pip.

See all articles