Heim Web-Frontend js-Tutorial Zusammenfassung der Wissenspunkte zum Diff-Algorithmus von Vue

Zusammenfassung der Wissenspunkte zum Diff-Algorithmus von Vue

May 28, 2018 am 11:26 AM
diff 总结 知识点

Dieser Artikel gibt Ihnen eine Zusammenfassung relevanter Wissenspunkte über den Diff-Algorithmus von Vue. Interessierte Freunde können sich darauf beziehen.

Virtueller Dom

Der Diff-Algorithmus muss zunächst das Konzept klären, dass das Objekt von Diff der virtuelle Dom ist und die Aktualisierung des realen Doms das Ergebnis des Diff-Algorithmus ist

Vnode-Basisklasse

 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
 }
Nach dem Login kopieren

Dieser Teil des Codes dient hauptsächlich dazu, die Bedeutung bestimmter Diff-Attribute im Diff-Algorithmus besser zu verstehen Verstehen Sie die Vnode-Instanz

Der Gesamtprozess

Die Kernfunktion ist die Patch-Funktion

  • isUndef Beurteilung (ob es ist undefiniert oder null)

  • // leerer Mount (wahrscheinlich als Komponente), neues Root-Element erstellencreateElm(vnode, insertedVnodeQueue) Hier können Sie feststellen, dass die erstellten Knoten nicht einzeln eingefügt werden, aber in eine Warteschlange für die einheitliche Stapelverarbeitung stellen

  • Kernfunktion 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)
   )
  )
 )
}
Nach dem Login kopieren

Hier ist eine äußere Vergleichsfunktion, die die Schlüssel und Tags direkt vergleicht und Daten von zwei Knoten (Beachten Sie, dass sich die Daten hier auf VNodeData beziehen) und der Typ für die Eingabe direkt verglichen wird.

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;
}
Nach dem Login kopieren

Dadurch wird bestätigt, ob die beiden Knoten einen weiteren Vergleichswert haben, andernfalls werden sie direkt ersetzt

Der Ersetzungsprozess ist hauptsächlich eine createElm-Funktion und die andere besteht darin, den oldVNode zu zerstören

// destroy old node
    if (isDef(parentElm)) {
     removeVnodes(parentElm, [oldVnode], 0, 0)
    } else if (isDef(oldVnode.tag)) {
     invokeDestroyHook(oldVnode)
    }
Nach dem Login kopieren

Einfügen Um den Prozess zu vereinfachen, müssen Sie den Typ des Knotens bestimmen und

createComponent aufrufen (es ermittelt, ob Kinder vorhanden sind, und ruft es dann rekursiv auf)

createComment

createTextNode

nach der Erstellung Nachdem Sie die Einfügefunktion

verwendet haben, müssen Sie die Hydrate-Funktion verwenden, um den virtuellen Dom und den realen Dom abzubilden

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)
   }
  }
 }
Nach dem Login kopieren

Kernfunktion

 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)
  }
 }
Nach dem Login kopieren

const el = vnode.el = oldVnode.el Dies ist ein sehr wichtiger Schritt. Lassen Sie vnode.el auf den aktuellen realen Dom verweisen, wenn el geändert wird. el wird sich synchron ändern.

  1. Vergleichen Sie die beiden Referenzen, um zu sehen, ob sie konsistent sind

  2. Ich weiß nicht, was asyncFactory danach macht, also kann ich es nicht Verstehe das.

  3. Statischer Knotenvergleichsschlüssel, danach erfolgt kein erneutes Rendern, direkt kopieren ComponentInstance (sobald der Befehl hier wirksam wird)

  4. Wenn vnode ein Textknoten oder Kommentarknoten ist, aber wenn vnode.text != oldVnode.text ist, müssen Sie nur den Textinhalt von vnode.elm aktualisieren

  5. Vergleich von Kinder

  • Wenn nur oldVnode untergeordnete Knoten hat, dann löschen Sie diese Knoten

  • Wenn nur vnode untergeordnete Knoten hat, dann Erstellen Sie diese untergeordneten Knoten. Wenn oldVnode lautet: Der Textknoten setzt den Text von vnode.elm auf die leere Zeichenfolge

  • , dann wird updateChildren aktualisiert. Dies wird später detailliert beschrieben >

  • Wenn oldVnode und vnode keine untergeordneten Knoten haben, oldVnode jedoch ein Textknoten oder Kommentarknoten ist, setzen Sie den Text von vnode.elm auf die leere Zeichenfolge

updateChildren

Der Fokus dieses Teils liegt immer noch auf dem gesamten Algorithmus

Erste vier Zeiger, oldStart, oldEnd, newStart, newEnd, zwei Arrays, 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)
  }
 }
Nach dem Login kopieren

Mehrere Situationen und Verarbeitung eines Schleifenvergleichs (das folgende ++ -- bezieht sich alle auf das ++ des Index --) Der Vergleich ist der zu vergleichende Knotenknoten und der Vergleich verwendet die sameVnode-Funktion. Es ist nicht wirklich kongruent.

Die Bedingung dafür, dass die gesamte Schleife nicht endet oldStartIdx <= oldEndIdx && newStartIdx <= newEndIdx

  1. oldStart = == newStart, oldStart++ newStart++

  2. oldEnd === newEnd, oldEnd-- newEnd--

  3. oldStart === newEnd, oldStart is am Ende der Warteschlange eingefügt oldStart++ newEnd--

  4. oldEnd === newStart, oldEnd wird am Anfang der Warteschlange oldEnd-- newStart++

    <🎜 eingefügt >
  5. Dies ist die einfache Möglichkeit, mit allen verbleibenden Situationen umzugehen. Nach der Verarbeitung findet newStart++ dasselbe Ding in alt, also verschieben Sie es vor oldStart
  6. Wenn Sie nicht dasselbe finden, erstellen Sie eines vor oldStart
  • Das ist es nicht abgeschlossen, nachdem die Schleife endet

  • Es gibt noch eine Zeit der Beurteilung, bevor sie abgeschlossen ist
  • 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)
      }
    Nach dem Login kopieren

    Um es einfach auszudrücken: Schauen Sie sich nach dem Ende der Schleife den Inhalt zwischen den vier Zeigern an Das alte Array und das neue Array werden zurückgegeben und weniger hinzugefügt. Das Obige ist für alle zusammengestellt. Ich hoffe, dass es Ihnen in Zukunft nützlich sein wird.

    Verwandte Artikel:

    Angular5-Methode zum Hinzufügen von Stilklassen zu den Tags der Komponente selbst

    vue-cli-Entwicklungsumgebung zur Implementierung Methode für domänenübergreifende Anfragen

    Detaillierte Erläuterung des Problems beim automatischen Build-Rem des Vue-cli-Webpack-Mobilterminals

    Das obige ist der detaillierte Inhalt vonZusammenfassung der Wissenspunkte zum Diff-Algorithmus von Vue. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn

Heiße KI -Werkzeuge

Undresser.AI Undress

Undresser.AI Undress

KI-gestützte App zum Erstellen realistischer Aktfotos

AI Clothes Remover

AI Clothes Remover

Online-KI-Tool zum Entfernen von Kleidung aus Fotos.

Undress AI Tool

Undress AI Tool

Ausziehbilder kostenlos

Clothoff.io

Clothoff.io

KI-Kleiderentferner

AI Hentai Generator

AI Hentai Generator

Erstellen Sie kostenlos Ai Hentai.

Heißer Artikel

R.E.P.O. Energiekristalle erklärten und was sie tun (gelber Kristall)
2 Wochen vor By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Beste grafische Einstellungen
2 Wochen vor By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. So reparieren Sie Audio, wenn Sie niemanden hören können
3 Wochen vor By 尊渡假赌尊渡假赌尊渡假赌

Heiße Werkzeuge

Notepad++7.3.1

Notepad++7.3.1

Einfach zu bedienender und kostenloser Code-Editor

SublimeText3 chinesische Version

SublimeText3 chinesische Version

Chinesische Version, sehr einfach zu bedienen

Senden Sie Studio 13.0.1

Senden Sie Studio 13.0.1

Leistungsstarke integrierte PHP-Entwicklungsumgebung

Dreamweaver CS6

Dreamweaver CS6

Visuelle Webentwicklungstools

SublimeText3 Mac-Version

SublimeText3 Mac-Version

Codebearbeitungssoftware auf Gottesniveau (SublimeText3)

Sammlung von Python-Spickzetteln. Welche Wissenspunkte beherrschen Sie? Sammlung von Python-Spickzetteln. Welche Wissenspunkte beherrschen Sie? Apr 26, 2023 pm 10:49 PM

Python ist derzeit die beliebteste Programmiersprache. Ich glaube, dass jeden Tag eine große Anzahl von Anfängern hinzukommen wird. Doch egal wie einfach eine Sprache zu erlernen ist, es gibt immer noch viele grundlegende Konzepte und Grundkenntnisse. Für einen Anfänger ist es immer noch schwierig, so viel auf einmal zu beherrschen. Heute haben wir viele Wissens-Spickzettel zum Thema Python zusammengestellt, von denen man sagen kann, dass sie umfassend sind. In Zukunft muss sich Mama keine Sorgen mehr machen, dass sich nicht alle Wissenspunkte merken können! Python-Grundlagen Python-Grundlagen Dieser Spickzettel enthält alle Grundkenntnisse von Python, von variablen Datentypen bis zu Listenzeichenfolgen, von der Umgebungsinstallation bis zur Verwendung häufig verwendeter Bibliotheken. Man kann sagen, dass er umfassend ist. Anfänger-Pytho

Fassen Sie die Verwendung der Funktion system() im Linux-System zusammen Fassen Sie die Verwendung der Funktion system() im Linux-System zusammen Feb 23, 2024 pm 06:45 PM

Zusammenfassung der Funktion system() unter Linux Im Linux-System ist die Funktion system() eine sehr häufig verwendete Funktion, mit der Befehlszeilenbefehle ausgeführt werden können. In diesem Artikel wird die Funktion system() ausführlich vorgestellt und einige spezifische Codebeispiele bereitgestellt. 1. Grundlegende Verwendung der Funktion system() Die Deklaration der Funktion system() lautet wie folgt: intsystem(constchar*command);

Ersetzen Sie svn diff durch vimdiff: ein Tool zum Vergleichen von Code Ersetzen Sie svn diff durch vimdiff: ein Tool zum Vergleichen von Code Jan 09, 2024 pm 07:54 PM

Unter Linux ist es sehr schwierig, den Befehl svndiff direkt zum Anzeigen von Codeänderungen zu verwenden. Daher habe ich im Internet nach einer besseren Lösung gesucht, nämlich die Verwendung von vimdiff als Tool zum Anzeigen von Code für svndiff, insbesondere für diejenigen, die daran gewöhnt sind vim. Es ist sehr praktisch. Wenn Sie den Befehl svndiff zum Vergleichen der Änderungen einer bestimmten Datei verwenden und beispielsweise den folgenden Befehl ausführen: $svndiff-r4420ngx_http_limit_req_module.c, wird der folgende Befehl tatsächlich an das Standard-Diff-Programm gesendet: -u-Lngx_http_limit_req_module.c (revision4420)-Lngx_

Enthüllung des Geheimnisses des HTML-Caching-Mechanismus: wesentliche Wissenspunkte Enthüllung des Geheimnisses des HTML-Caching-Mechanismus: wesentliche Wissenspunkte Jan 23, 2024 am 08:51 AM

Das Geheimnis des HTML-Caching-Mechanismus: Wesentliche Wissenspunkte, spezifische Codebeispiele sind erforderlich. Bei der Webentwicklung war die Leistung schon immer ein wichtiger Gesichtspunkt. Der HTML-Caching-Mechanismus ist einer der Schlüssel zur Verbesserung der Leistung von Webseiten. In diesem Artikel werden die Prinzipien und praktischen Fähigkeiten des HTML-Caching-Mechanismus erläutert und spezifische Codebeispiele bereitgestellt. 1. Prinzip des HTML-Caching-Mechanismus Während des Zugriffs auf eine Webseite fordert der Browser den Server auf, die HTML-Seite über das HTTP-Protokoll abzurufen. Der HTML-Caching-Mechanismus besteht darin, HTML-Seiten im Browser zwischenzuspeichern

Ausführliche Erklärung der MySQL-Datentypen: Was Sie wissen müssen Ausführliche Erklärung der MySQL-Datentypen: Was Sie wissen müssen Jun 15, 2023 am 08:56 AM

MySQL ist eines der beliebtesten relationalen Datenbankverwaltungssysteme weltweit und wird aufgrund seiner Zuverlässigkeit, hohen Sicherheit, hohen Skalierbarkeit und relativ geringen Kosten häufig verwendet. MySQL-Datentypen definieren die Speichermethoden verschiedener Datentypen und sind ein wichtiger Bestandteil von MySQL. In diesem Artikel werden die Datentypen von MySQL und einige Wissenspunkte, auf die in praktischen Anwendungen geachtet werden muss, ausführlich erläutert. 1. MySQL-Datentypklassifizierung MySQL-Datentypen können in die folgenden Kategorien unterteilt werden: Ganzzahltypen: einschließlich TINYINT,

Einführung in die Netzwerksicherheit: Was sind die wesentlichen Wissenspunkte für Einsteiger? Einführung in die Netzwerksicherheit: Was sind die wesentlichen Wissenspunkte für Einsteiger? Jun 11, 2023 am 09:57 AM

Einführung in die Netzwerksicherheit: Was sind die wesentlichen Wissenspunkte für Einsteiger? In den letzten Jahren hat die Netzwerksicherheit mit der rasanten Entwicklung des Internets immer mehr Aufmerksamkeit auf sich gezogen. Für viele Menschen ist die Netzwerksicherheit jedoch immer noch ein unbekannter Ozean. Welche grundlegenden Kenntnisse müssen Anfänger also beherrschen, um mit der Netzwerksicherheit zu beginnen? Dieser Artikel wird es für Sie klären. 1. Netzwerkangriffe und -bedrohungen Zunächst einmal ist das Verständnis der Arten von Netzwerkangriffen und -bedrohungen ein Wissenspunkt, den man beherrschen muss, um mit der Netzwerksicherheit beginnen zu können. Es gibt viele Arten von Cyberangriffen wie Phishing-Angriffe, Malware und Ransomware

Aufgedeckte Oracle-Datentypen: Wissenspunkte, die Sie kennen müssen Aufgedeckte Oracle-Datentypen: Wissenspunkte, die Sie kennen müssen Mar 07, 2024 pm 05:18 PM

Das Geheimnis der Oracle-Datentypen: Wissenspunkte, die Sie verstehen müssen, und spezifische Codebeispiele. Als eines der weltweit führenden Datenbankverwaltungssysteme spielt Oracle eine wichtige Rolle bei der Datenspeicherung und -verarbeitung. In Oracle ist der Datentyp ein sehr wichtiges Konzept, das das Speicherformat, den Bereich und die Betriebsmethode der Daten in der Datenbank definiert. In diesem Artikel werden verschiedene Wissenspunkte zu Oracle-Datentypen aufgezeigt und deren Verwendung und Eigenschaften anhand spezifischer Codebeispiele demonstriert. 1. Allgemeine Datentypen, Zeichendatentypen

Zusammenfassung der Git-Workflow-Management-Erfahrung Zusammenfassung der Git-Workflow-Management-Erfahrung Nov 03, 2023 pm 06:45 PM

Zusammenfassung der Git-Workflow-Management-Erfahrung Einführung: In der Softwareentwicklung ist die Versionsverwaltung ein sehr wichtiges Glied. Als eines der derzeit beliebtesten Versionsverwaltungstools machen die leistungsstarken Branch-Management-Funktionen von Git die Zusammenarbeit im Team effizienter und flexibler. In diesem Artikel werden die Erfahrungen mit dem Git-Workflow-Management zusammengefasst und weitergegeben. 1. Einführung in den Git-Workflow Git unterstützt eine Vielzahl von Workflows, und Sie können den geeigneten Workflow entsprechend der tatsächlichen Situation des Teams auswählen. Zu den gängigen Git-Workflows gehören der zentralisierte Workflow, der Feature-Branch-Workflow und GitF

See all articles