Skip to content

Commit

Permalink
Site updated: 2019-04-13 16:29:49
Browse files Browse the repository at this point in the history
  • Loading branch information
liyang0207 committed Apr 13, 2019
1 parent 5612ed8 commit 74e3ae7
Show file tree
Hide file tree
Showing 3 changed files with 4 additions and 4 deletions.
4 changes: 2 additions & 2 deletions 2019/04/13/React源码学习-Fiber遍历/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@
<meta property="og:locale" content="zh-Hans">
<meta property="og:image" content="http://yoursite.com/images/react/react-fiber-structure01.png">
<meta property="og:image" content="http://yoursite.com/images/react/react-fiber-structure02.gif">
<meta property="og:updated_time" content="2019-04-13T07:47:26.787Z">
<meta property="og:updated_time" content="2019-04-13T08:28:57.253Z">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="React源码学习-Fiber遍历">
<meta name="twitter:description" content="react在自己的v16版本中将底层的reconciliation过程进行了重大更改,之前v15中使用同步递归算法进行组件的diff,我们知道,浏览器需要一定的刷新帧率(大概16ms渲染一次,FPS为60)才能确保页面不会可见的卡顿,而react一旦同步遍历的组件过多,将会引起页面掉帧,应用就会显得卡顿。因此,react花了大概两年时间优化,提出了Fiber结构,以链表的形式实现了操作树的新算法,">
Expand Down Expand Up @@ -409,7 +409,7 @@ <h2 id="一撇React源码"><a href="#一撇React源码" class="headerlink" title
<p>先来看下<code>performUnitOfWork</code><code>beginWork</code>函数:</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">performUnitOfWork</span>(<span class="params">workInProgress: Fiber</span>): <span class="title">Fiber</span> </span>&#123;</span><br><span class="line"> <span class="keyword">let</span> next = beginWork(workInProgress); <span class="comment">// 启动工作</span></span><br><span class="line"> <span class="keyword">if</span> (next === <span class="literal">null</span>) &#123;</span><br><span class="line"> next = completeUnitOfWork(workInProgress);</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="keyword">return</span> next;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">beginWork</span>(<span class="params">workInProgress: Fiber</span>): <span class="title">Fiber</span> </span>&#123;</span><br><span class="line"> <span class="comment">//主要函数,这里根据fiber节点的tag来进行不同的操作,以后详细分析</span></span><br><span class="line"> <span class="built_in">console</span>.log(workInProgress.name);</span><br><span class="line"> <span class="keyword">return</span> workInProgress.child; <span class="comment">// 返回下一个子节点或者null</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>如果有下一个子节点,它将被赋值给<code>workLoop</code>函数中的<code>nextUnitOfWork</code>变量,继续往下遍历;如果没有子节点,则代表这个分支的遍历到达了末尾,因此就完成了当前节点,之后,就需要找到这个完成节点的兄弟节点开始下一个分支的遍历,最后再回溯到父节点。这些在<code>completeUnitOfWork</code>函数中完成:</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">completeUnitOfWork</span>(<span class="params">workInProgress: Fiber</span>): <span class="title">Fiber</span> </span>&#123;</span><br><span class="line"> <span class="keyword">while</span>(<span class="literal">true</span>) &#123;</span><br><span class="line"> <span class="keyword">let</span> siblingFiber = workInProgress.sibling;</span><br><span class="line"> <span class="keyword">let</span> returnFiber = workInProgress.return;</span><br><span class="line"> </span><br><span class="line"> nextUnitOfWork = completeWork(workInProgress);</span><br><span class="line"> <span class="keyword">if</span> (siblingFiber !== <span class="literal">null</span>) &#123;</span><br><span class="line"> <span class="comment">//有兄弟节点,返回给perform work这个节点</span></span><br><span class="line"> <span class="keyword">return</span> siblingFiber;</span><br><span class="line"> &#125; <span class="keyword">else</span> <span class="keyword">if</span> (returnFiber !== <span class="literal">null</span>) &#123;</span><br><span class="line"> <span class="comment">//有父节点,一层一层上去完成父节点</span></span><br><span class="line"> workInProgress = returnFiber;</span><br><span class="line"> <span class="keyword">continue</span>;</span><br><span class="line"> &#125; <span class="keyword">else</span> &#123;</span><br><span class="line"> <span class="comment">// 到达了root</span></span><br><span class="line"> <span class="keyword">return</span> <span class="literal">null</span>;</span><br><span class="line"> &#125;</span><br><span class="line"> &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">completeWork</span>(<span class="params">workInProgress</span>) </span>&#123;</span><br><span class="line"> <span class="comment">//主要函数,这里根据fiber节点的tag来进行不同的操作,以后详细分析</span></span><br><span class="line"> <span class="built_in">console</span>.log(workInProgress.name);</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">null</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">completeUnitOfWork</span>(<span class="params">workInProgress: Fiber</span>): <span class="title">Fiber</span> </span>&#123;</span><br><span class="line"> <span class="keyword">while</span>(<span class="literal">true</span>) &#123;</span><br><span class="line"> <span class="keyword">const</span> current = workInProgress.alternate;</span><br><span class="line"> <span class="keyword">let</span> siblingFiber = workInProgress.sibling;</span><br><span class="line"> <span class="keyword">let</span> returnFiber = workInProgress.return;</span><br><span class="line"> </span><br><span class="line"> nextUnitOfWork = completeWork(current, workInProgress);</span><br><span class="line"> <span class="keyword">if</span> (siblingFiber !== <span class="literal">null</span>) &#123;</span><br><span class="line"> <span class="comment">//有兄弟节点,返回给perform work这个节点</span></span><br><span class="line"> <span class="keyword">return</span> siblingFiber;</span><br><span class="line"> &#125; <span class="keyword">else</span> <span class="keyword">if</span> (returnFiber !== <span class="literal">null</span>) &#123;</span><br><span class="line"> <span class="comment">//有父节点,一层一层上去完成父节点</span></span><br><span class="line"> workInProgress = returnFiber;</span><br><span class="line"> <span class="keyword">continue</span>;</span><br><span class="line"> &#125; <span class="keyword">else</span> &#123;</span><br><span class="line"> <span class="comment">// 到达了root</span></span><br><span class="line"> <span class="keyword">return</span> <span class="literal">null</span>;</span><br><span class="line"> &#125;</span><br><span class="line"> &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">completeWork</span>(<span class="params">current, workInProgress</span>) </span>&#123;</span><br><span class="line"> <span class="comment">//主要函数,这里根据fiber节点的tag来进行不同的操作,以后详细分析</span></span><br><span class="line"> <span class="built_in">console</span>.log(workInProgress.name);</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">null</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><code>workInProgress</code>没有子节点的时候,进入此函数,走<code>completeWork</code>完成当前节点的工作。然后寻找它是否有兄弟节点,如果找到,<code>react</code>退出<code>completeUnitOfWork</code>并返回这个兄弟节点,交给<code>nextUnitOfWork</code>去进行下一个分支的工作。这里,<code>react</code>只是完成了第一个子分支的工作,父节点的工作还没有完成,只有在完成所有子分支节点的工作后,才会向上去完成父节点的工作。</p>
<p>上面的4个函数,<code>performUnitOfWork</code><code>completeUnitOfWork</code>主要用于迭代工作,主要的活动则在<code>beginWork</code><code>completeWork</code>函数中进行(react源码为这两个方法各自分配了单个文件来写)。</p>
<p>这篇博客只是简单总结了一点点<code>fiber</code>构建的知识,源码的学习实在太过复杂太难以理解,只能一个点一个点的去突破和理解,正如乔布斯在斯坦福大学中的演讲所说:</p>
Expand Down
2 changes: 1 addition & 1 deletion css/main.css
Original file line number Diff line number Diff line change
Expand Up @@ -1684,7 +1684,7 @@ pre .javascript .function {
width: 4px;
height: 4px;
border-radius: 50%;
background: #ebffff;
background: #ffff7f;
}
.links-of-blogroll {
font-size: 13px;
Expand Down
Loading

0 comments on commit 74e3ae7

Please sign in to comment.