<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: zhenghaoyang24</title>
    <description>The latest articles on DEV Community by zhenghaoyang24 (@zhenghaoyang24).</description>
    <link>https://dev.to/zhenghaoyang24</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3578458%2F752a9c45-d324-4fcf-953d-b1f0f25a7e96.png</url>
      <title>DEV Community: zhenghaoyang24</title>
      <link>https://dev.to/zhenghaoyang24</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/zhenghaoyang24"/>
    <language>en</language>
    <item>
      <title>Virtual DOM and Diff Algorithm</title>
      <dc:creator>zhenghaoyang24</dc:creator>
      <pubDate>Wed, 03 Jun 2026 14:16:16 +0000</pubDate>
      <link>https://dev.to/zhenghaoyang24/virtual-dom-and-diff-algorithm-497n</link>
      <guid>https://dev.to/zhenghaoyang24/virtual-dom-and-diff-algorithm-497n</guid>
      <description>&lt;h2&gt;
  
  
  Virtual DOM
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Virtual DOM&lt;/strong&gt; is essentially a data structure that &lt;strong&gt;uses JavaScript objects to describe the structure of the real DOM&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Real DOM&lt;/strong&gt;: A large, complex object tree provided by the browser. Directly manipulating it is expensive (triggers reflows and repaints).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Virtual DOM&lt;/strong&gt;: Lightweight JS objects that are cheap to manipulate.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Real HTML&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"app"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"container"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;Hello&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Corresponding Virtual DOM&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;vnode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;tag&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;div&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;props&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;app&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;container&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;children&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;tag&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;h1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;props&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt; &lt;span class="na"&gt;children&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hello&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Virtual DOM is the carrier of the Diff algorithm. When data changes, instead of directly manipulating the real DOM, we generate a new Virtual DOM tree, then use the Diff algorithm to compare the old and new trees, find the minimal differences, and finally update the real DOM with minimal cost.&lt;/p&gt;

&lt;p&gt;Therefore, the statement "Virtual DOM is faster than real DOM" is not precise. The Virtual DOM itself is just a JavaScript object that facilitates diffing; the real performance gain comes from the minimal update strategy computed by the Diff algorithm. A more accurate formula is:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Efficient view update = Virtual DOM + Diff algorithm + Minimal DOM operations&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Diff Algorithm
&lt;/h2&gt;

&lt;p&gt;The Diff algorithm is a comparison algorithm used to find the minimal differences between old and new Virtual DOM trees. It then updates only the changed parts of the real DOM, skipping unchanged nodes, thereby improving update efficiency.&lt;/p&gt;

&lt;h3&gt;
  
  
  Comparison Flow
&lt;/h3&gt;

&lt;p&gt;The Diff algorithm uses &lt;strong&gt;depth-first traversal&lt;/strong&gt; and performs &lt;strong&gt;comparison only at the same level&lt;/strong&gt; for child nodes. Starting from the root, it first compares the current node; if reusable, it recursively enters the child node arrays for comparison. After processing child nodes, it moves to the next sibling node at the same level.&lt;/p&gt;

&lt;p&gt;When reactive data inside a component changes, it triggers the setter, which notifies all subscribers (Watchers) via &lt;code&gt;Dep.notify&lt;/code&gt;, ultimately calling the &lt;code&gt;patch&lt;/code&gt; method for comparison.&lt;/p&gt;

&lt;h4&gt;
  
  
  patch
&lt;/h4&gt;

&lt;p&gt;The core of &lt;code&gt;patch&lt;/code&gt; is to determine, via &lt;code&gt;sameVnode&lt;/code&gt;, whether the old and new virtual nodes are of the same type:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Yes&lt;/strong&gt;: Call &lt;code&gt;patchVnode&lt;/code&gt; for deep comparison and reuse.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No&lt;/strong&gt;: Direct replacement — remove the real DOM corresponding to the old node, create and insert the new node.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;patch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;oldVnode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;newVnode&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;sameVnode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;oldVnode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;newVnode&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Same type, compare deeply&lt;/span&gt;
    &lt;span class="nf"&gt;patchVnode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;oldVnode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;newVnode&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Different types, replace entirely&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;parent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;oldVnode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;parentNode&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;el&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createElm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;newVnode&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;// Create real DOM from new vnode&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;parent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;parent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;insertBefore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;oldVnode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;// Insert new node&lt;/span&gt;
      &lt;span class="nx"&gt;parent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;removeChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;oldVnode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;       &lt;span class="c1"&gt;// Remove old node&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;sameVnode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="c1"&gt;// same key&lt;/span&gt;
    &lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tag&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tag&lt;/span&gt;    &lt;span class="c1"&gt;// same tag name&lt;/span&gt;
    &lt;span class="nf"&gt;sameInputType&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// For input tags, same type&lt;/span&gt;
    &lt;span class="c1"&gt;// other conditions ...&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  patchVnode
&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;patchVnode&lt;/code&gt; is used to compare the properties, text, and children of two &lt;strong&gt;same-type&lt;/strong&gt; nodes. The general flow:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;If the old and new nodes are identical (&lt;code&gt;oldVnode === newVnode&lt;/code&gt;), return immediately.&lt;/li&gt;
&lt;li&gt;If the new node is a text node (i.e., &lt;code&gt;newVnode.text&lt;/code&gt; exists) and differs from the old text, update the real DOM text content.&lt;/li&gt;
&lt;li&gt;Otherwise, the nodes may have children:

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Both have children&lt;/strong&gt;: Call &lt;code&gt;updateChildren&lt;/code&gt; for head/tail pointer comparison.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Only new node has children&lt;/strong&gt;: Create new child nodes and insert them into the real DOM.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Only old node has children&lt;/strong&gt;: Remove old child nodes from the real DOM.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Neither has children&lt;/strong&gt;: No extra processing.
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;patchVnode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;oldVnode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;newVnode&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;el&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;newVnode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;el&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;oldVnode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Reuse real DOM reference&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;oldCh&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;oldVnode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;newCh&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;newVnode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;

  &lt;span class="c1"&gt;// Same object, no processing needed&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;oldVnode&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;newVnode&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;

  &lt;span class="c1"&gt;// New node is a text node&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;newVnode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;oldVnode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="nx"&gt;newVnode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;textContent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;newVnode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// New node has children&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;oldCh&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;newCh&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// Both have children, enter core diff&lt;/span&gt;
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;oldCh&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="nx"&gt;newCh&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;updateChildren&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;oldCh&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;newCh&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;newCh&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// Only new has children: create and add&lt;/span&gt;
      &lt;span class="nf"&gt;addVnodes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;newCh&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;newCh&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;oldCh&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// Only old has children: remove old children&lt;/span&gt;
      &lt;span class="nf"&gt;removeVnodes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;oldCh&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;oldCh&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="c1"&gt;// If neither has children, do nothing&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  updateChildren
&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;updateChildren&lt;/code&gt; is the core of the double-ended Diff (head/tail pointer method). It compares two arrays of &lt;strong&gt;child nodes at the same level&lt;/strong&gt;. Four pointers are maintained: &lt;code&gt;oldStartIdx&lt;/code&gt;, &lt;code&gt;oldEndIdx&lt;/code&gt;, &lt;code&gt;newStartIdx&lt;/code&gt;, &lt;code&gt;newEndIdx&lt;/code&gt;. The loop executes the following logic:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Quick head/tail attempts&lt;/strong&gt; (in order):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;oldStart vs newStart&lt;/strong&gt;: If same, patch and move both head pointers right (no DOM movement needed).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;oldEnd vs newEnd&lt;/strong&gt;: If same, patch and move both tail pointers left (no DOM movement needed).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;oldStart vs newEnd&lt;/strong&gt;: If same, patch and move the real DOM node of oldStart &lt;strong&gt;after oldEnd&lt;/strong&gt;, then move oldStart right and newEnd left.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;oldEnd vs newStart&lt;/strong&gt;: If same, patch and move the real DOM node of oldEnd &lt;strong&gt;before oldStart&lt;/strong&gt;, then move oldEnd left and newStart right.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Out-of-order lookup&lt;/strong&gt;: If none of the above four comparisons match, look for the newStart node within the old node range (&lt;code&gt;oldStartIdx..oldEndIdx&lt;/code&gt;):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Found&lt;/strong&gt;: Patch, then move the real DOM of that old node &lt;strong&gt;before oldStart (before unprocessed nodes)&lt;/strong&gt;, mark that position in the old array as &lt;code&gt;undefined&lt;/code&gt; (to avoid duplicate processing), and only move &lt;code&gt;newStartIdx&lt;/code&gt; right.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Not found&lt;/strong&gt;: Treat as a new node, create its real DOM and insert &lt;strong&gt;before oldStart&lt;/strong&gt;, then move &lt;code&gt;newStartIdx&lt;/code&gt; right.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Skipping boundaries&lt;/strong&gt;: At the start of each loop, if &lt;code&gt;oldStartIdx&lt;/code&gt; or &lt;code&gt;oldEndIdx&lt;/code&gt; points to &lt;code&gt;undefined&lt;/code&gt;, simply move that pointer inward and skip.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Cleanup&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If &lt;code&gt;oldStartIdx &amp;gt; oldEndIdx&lt;/code&gt; (old nodes exhausted first), the remaining new nodes are all additions — batch create and insert.&lt;/li&gt;
&lt;li&gt;If &lt;code&gt;newStartIdx &amp;gt; newEndIdx&lt;/code&gt; (new nodes exhausted first), the remaining old nodes (non-&lt;code&gt;undefined&lt;/code&gt;) are all to be removed.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Example walkthrough&lt;/strong&gt;: Consider the following old and new nodes. The initial real DOM is &lt;code&gt;a, b, c, d, e&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- Old nodes --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;ul&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&lt;/span&gt;a&lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&amp;lt;li&amp;gt;&lt;/span&gt;b&lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&amp;lt;li&amp;gt;&lt;/span&gt;c&lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&amp;lt;li&amp;gt;&lt;/span&gt;d&lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&amp;lt;li&amp;gt;&lt;/span&gt;e&lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;
&lt;span class="c"&gt;&amp;lt;!-- New nodes --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;ul&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&lt;/span&gt;a&lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&amp;lt;li&amp;gt;&lt;/span&gt;d&lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&amp;lt;li&amp;gt;&lt;/span&gt;e&lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&amp;lt;li&amp;gt;&lt;/span&gt;f&lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Initial state:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DOM: a b c d e
old: [a] b c d [e]    (os=0, oe=4)
new: [a] d e [f]      (ns=0, ne=3)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 1&lt;/strong&gt;: oldStart &lt;code&gt;a&lt;/code&gt; vs newStart &lt;code&gt;a&lt;/code&gt; — match.&lt;/p&gt;

&lt;p&gt;No DOM movement, &lt;code&gt;os++&lt;/code&gt;, &lt;code&gt;ns++&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DOM: a b c d e
old: a [b] c d [e]   (os=1, oe=4)
new: a [d] e [f]     (ns=1, ne=3)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 2&lt;/strong&gt;: None of the four comparisons match. Look for newStart &lt;code&gt;d&lt;/code&gt; in old range &lt;code&gt;[b,c,d,e]&lt;/code&gt;, found at index 3.&lt;br&gt;&lt;br&gt;
Move the real DOM of &lt;code&gt;d&lt;/code&gt; before oldStart &lt;code&gt;b&lt;/code&gt;, mark &lt;code&gt;old[3]&lt;/code&gt; as &lt;code&gt;undefined&lt;/code&gt;, &lt;code&gt;ns++&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DOM: a d b c e
old: a [b] c undefined [e]   (os=1, oe=4)
new: a d [e] [f]             (ns=2, ne=3)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 3&lt;/strong&gt;: oldEnd &lt;code&gt;e&lt;/code&gt; vs newStart &lt;code&gt;e&lt;/code&gt; — match.&lt;/p&gt;

&lt;p&gt;Move the real DOM of oldEnd &lt;code&gt;e&lt;/code&gt; before oldStart &lt;code&gt;b&lt;/code&gt; (i.e., after &lt;code&gt;d&lt;/code&gt;), &lt;code&gt;oe--&lt;/code&gt;, &lt;code&gt;ns++&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DOM: a d e b c
old: a [b] c undefined e   (os=1, oe=3, oe now points to undefined at index 3)
new: a d e [f]             (ns=3, ne=3)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note: At the start of the next loop, because &lt;code&gt;oe&lt;/code&gt; points to &lt;code&gt;undefined&lt;/code&gt;, it will move left again to index 2 (&lt;code&gt;c&lt;/code&gt;), so the range becomes &lt;code&gt;os=1, oe=2&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 4&lt;/strong&gt;: Current valid range &lt;code&gt;[b, c]&lt;/code&gt;, newStart is &lt;code&gt;f&lt;/code&gt;. All four comparisons fail, and &lt;code&gt;f&lt;/code&gt; is not found.&lt;br&gt;&lt;br&gt;
Create the real DOM for &lt;code&gt;f&lt;/code&gt; and insert before oldStart &lt;code&gt;b&lt;/code&gt;, &lt;code&gt;ns++&lt;/code&gt; → &lt;code&gt;ns=4 &amp;gt; ne&lt;/code&gt;, loop ends.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DOM: a d e f b c
old: a [b] [c] undefined e   (os=1, oe=2)
new: a d e [f] []          (ns&amp;gt;ne)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Cleanup&lt;/strong&gt;: &lt;code&gt;ns &amp;gt; ne&lt;/code&gt;, delete the old range from &lt;code&gt;os=1&lt;/code&gt; to &lt;code&gt;oe=2&lt;/code&gt; (i.e., &lt;code&gt;b&lt;/code&gt; and &lt;code&gt;c&lt;/code&gt;).&lt;br&gt;&lt;br&gt;
Final real DOM: &lt;code&gt;a, d, e, f&lt;/code&gt;, matching the new Virtual DOM structure.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>vue</category>
      <category>programming</category>
      <category>python</category>
    </item>
    <item>
      <title>I want to learn React. I have already mastered HTML, CSS, JS, TS, and Vue, but I feel that the React ecosystem is too diverse, making it difficult for me to know where to start. Do you have any suggestions?</title>
      <dc:creator>zhenghaoyang24</dc:creator>
      <pubDate>Tue, 06 Jan 2026 08:08:36 +0000</pubDate>
      <link>https://dev.to/zhenghaoyang24/i-want-to-learn-react-i-have-already-mastered-html-css-js-ts-and-vue-but-i-feel-that-the-g6n</link>
      <guid>https://dev.to/zhenghaoyang24/i-want-to-learn-react-i-have-already-mastered-html-css-js-ts-and-vue-but-i-feel-that-the-g6n</guid>
      <description></description>
      <category>beginners</category>
      <category>discuss</category>
      <category>javascript</category>
      <category>react</category>
    </item>
  </channel>
</rss>
