{"componentChunkName":"component---src-templates-blog-post-js","path":"/2019/10/31/利用fiber-reconciler实现简易的reactdom-render操作/","result":{"data":{"content":{"edges":[{"node":{"id":"1eb0b1ed-515c-5154-b2c8-c8bf9824a42f","html":"<h2 id=\"reconciler作用\" style=\"position:relative;\"><a href=\"#reconciler%E4%BD%9C%E7%94%A8\" aria-label=\"reconciler作用 permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Reconciler作用</h2>\n<p>目前React的应用场景不仅限于Web App，也有很多人用来完成2D画图库、3D图形库、命令行库等工具。无论处于哪种宿主环境中，React生态大致包括如下基本概念/功能：</p>\n<ul>\n<li>host内置组件（div, span, img等）</li>\n<li>函数式组件</li>\n<li>类组件</li>\n<li>props, state</li>\n<li>effects, lifecycle</li>\n<li>key, ref, context</li>\n<li>React.lazy, error boundaries</li>\n<li>concurrent mode, Suspense</li>\n</ul>\n<p>除内置组件与宿主相关(如React Native中包括View, Text等特定组件）以外，上述逻辑功能在跨平台的环境中是通用的。</p>\n<p>这些通用的部分就交给reconciler来实现，当有更新出现时，reconciler就会调用render。这篇文章不会介绍调度算法的内容，可以阅读<a href=\"https://libin1991.github.io/2019/07/01/%E7%90%86%E8%A7%A3-React-Fiber-%E6%9E%B6%E6%9E%84/\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">理解React Fiber架构</a>了解更多。</p>\n<p>Sophie Alpert在会上还提到了react-reconciler使用时的两个模式：Mutation模式和Persistent模式。</p>\n<ol>\n<li>Mutation模式</li>\n</ol>\n<p>我们对DOM的修改，即ReactDOM就遵循该模式。我们通过改变已有的BOM/DOM的属性来render，这也是DOM自身的工作原理。伪代码如下：</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\">view <span class=\"token operator\">=</span> <span class=\"token function\">createView</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n<span class=\"token function\">updateView</span><span class=\"token punctuation\">(</span>view<span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span>color<span class=\"token operator\">:</span> <span class=\"token string\">'red'</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span> <span class=\"token comment\">// 更新已有视图</span>\n\ndiv <span class=\"token operator\">=</span> document<span class=\"token punctuation\">.</span><span class=\"token function\">createElement</span><span class=\"token punctuation\">(</span><span class=\"token string\">'div'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\ndiv<span class=\"token punctuation\">.</span>style<span class=\"token punctuation\">.</span>color <span class=\"token operator\">=</span> <span class=\"token string\">'red'</span><span class=\"token punctuation\">;</span></code></pre></div>\n<ol start=\"2\">\n<li>Persistent模式</li>\n</ol>\n<p>当API将系统当成Immutable Object时，我们会将整个视图替换成另一版本。因为React Native拥有对host的绝对控制，所以下一版本的RN采用此模式实现Concurrency。</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\">view <span class=\"token operator\">=</span> <span class=\"token function\">createView</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token function\">cloneView</span><span class=\"token punctuation\">(</span>view<span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span>color<span class=\"token operator\">:</span> <span class=\"token string\">'red'</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 克隆新视图</span></code></pre></div>\n<p>现在我们要用react-reconciler来替代ReactDOM，做一个简版的渲染器，以便更好的了解React的工作原理。实现诸如以下指令：</p>\n<ul>\n<li>渲染一个新视图</li>\n<li>动态显示dom</li>\n<li>利用自定义props更新背景色</li>\n</ul>\n<h2 id=\"实现reactdommini\" style=\"position:relative;\"><a href=\"#%E5%AE%9E%E7%8E%B0reactdommini\" aria-label=\"实现reactdommini permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>实现ReactDOMMini</h2>\n<p>首先，我们用create-react-app创建一个项目，安装react-reconciler依赖。然后，用我们要实现的ReactDOMMini替代ReactDOM。</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token comment\">// import ReactDOM from 'react-dom';</span>\n<span class=\"token keyword\">import</span> ReactDOMMini <span class=\"token keyword\">from</span> <span class=\"token string\">'./ReactDOMMini'</span><span class=\"token punctuation\">;</span>\n<span class=\"token operator\">...</span>\nReactDOMMini<span class=\"token punctuation\">.</span><span class=\"token function\">render</span><span class=\"token punctuation\">(</span><span class=\"token operator\">&lt;</span>App <span class=\"token operator\">/</span><span class=\"token operator\">></span><span class=\"token punctuation\">,</span> document<span class=\"token punctuation\">.</span><span class=\"token function\">getElementById</span><span class=\"token punctuation\">(</span><span class=\"token string\">'root'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre></div>\n<h3 id=\"渲染基础视图\" style=\"position:relative;\"><a href=\"#%E6%B8%B2%E6%9F%93%E5%9F%BA%E7%A1%80%E8%A7%86%E5%9B%BE\" aria-label=\"渲染基础视图 permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>渲染基础视图</h3>\n<p>在ReactDOMMini中，我们需要对宿主环境进行配置，然后更新视图。react-reconciler的API如下：</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">const</span> Reconciler <span class=\"token operator\">=</span> <span class=\"token function\">require</span><span class=\"token punctuation\">(</span><span class=\"token string\">'react-reconciler'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">const</span> HostConfig <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token comment\">// You'll need to implement some methods here.</span>\n  <span class=\"token comment\">// See below for more information and examples.</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">const</span> MyRenderer <span class=\"token operator\">=</span> <span class=\"token function\">Reconciler</span><span class=\"token punctuation\">(</span>HostConfig<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">const</span> RendererPublicAPI <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token function\">render</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">element<span class=\"token punctuation\">,</span> container<span class=\"token punctuation\">,</span> callback</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token comment\">// Call MyRenderer.updateContainer() to schedule changes on the roots.</span>\n    <span class=\"token comment\">// See ReactDOM, React Native, or React ART for practical examples.</span>\n  <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n\nmodule<span class=\"token punctuation\">.</span>exports <span class=\"token operator\">=</span> RendererPublicAPI<span class=\"token punctuation\">;</span></code></pre></div>\n<p>我们需要在hostConfig里对宿主环境进行配置，描述协调器工作时需要宿主环境发生怎样的变化。HostConfig相当于一个桥梁，用户通过参数声明的方式传给<a href=\"https://github.com/facebook/react/blob/master/packages/react-reconciler/src/forks/ReactFiberHostConfig.custom.js\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">配置项</a>，reconciler将其作为module引入。</p>\n<p>在这里也可以看到DOM的<a href=\"https://github.com/facebook/react/blob/master/packages/react-dom/src/client/ReactDOMHostConfig.js\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">HostConfig的实现</a>。</p>\n<p>我们先写一些基本的配置项：</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">const</span> hostConfig <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span>\n    supportsMutation<span class=\"token operator\">:</span> <span class=\"token boolean\">true</span><span class=\"token punctuation\">,</span> <span class=\"token comment\">// 开启mutating模式</span>\n    <span class=\"token function-variable function\">createInstance</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">(</span>\n        <span class=\"token parameter\">type<span class=\"token punctuation\">,</span>\n        props<span class=\"token punctuation\">,</span>\n        rootContainerInstance<span class=\"token punctuation\">,</span>\n        hostContext<span class=\"token punctuation\">,</span>\n        internalInstanceHandle</span>\n    <span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n    <span class=\"token function-variable function\">createTextInstance</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">(</span>\n        <span class=\"token parameter\">text<span class=\"token punctuation\">,</span>\n        rootContainerInstance<span class=\"token punctuation\">,</span>\n        hostContext<span class=\"token punctuation\">,</span>\n        internalInstanceHandle</span>\n    <span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n    <span class=\"token function-variable function\">appendInitialChild</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">parent<span class=\"token punctuation\">,</span> child</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n    <span class=\"token function-variable function\">appendChildToContainer</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">container<span class=\"token punctuation\">,</span> child</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n    <span class=\"token function-variable function\">removeChildFromContainer</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">container<span class=\"token punctuation\">,</span> child</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n    <span class=\"token function-variable function\">getRootHostContext</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n    <span class=\"token function-variable function\">prepareForCommit</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n    <span class=\"token function-variable function\">resetAfterCommit</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n    <span class=\"token function-variable function\">getChildHostContext</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n    <span class=\"token function-variable function\">shouldSetTextContent</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n    <span class=\"token function-variable function\">finalizeInitialChildren</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span><span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span>\n<span class=\"token keyword\">const</span> reconciler <span class=\"token operator\">=</span> <span class=\"token function\">reactReconciler</span><span class=\"token punctuation\">(</span>hostConfig<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">export</span> <span class=\"token keyword\">default</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token function\">render</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">reactElement<span class=\"token punctuation\">,</span> domEle<span class=\"token punctuation\">,</span> callback</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n        <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">!</span>domEle<span class=\"token punctuation\">.</span>_rootContainer<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n            domEle<span class=\"token punctuation\">.</span>_rootContainer <span class=\"token operator\">=</span> reconciler<span class=\"token punctuation\">.</span><span class=\"token function\">createContainer</span><span class=\"token punctuation\">(</span>domEle<span class=\"token punctuation\">,</span> <span class=\"token boolean\">false</span><span class=\"token punctuation\">,</span> <span class=\"token boolean\">false</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n        <span class=\"token punctuation\">}</span>\n        reconciler<span class=\"token punctuation\">.</span><span class=\"token function\">updateContainer</span><span class=\"token punctuation\">(</span>reactElement<span class=\"token punctuation\">,</span> domEle<span class=\"token punctuation\">.</span>_rootContainer<span class=\"token punctuation\">,</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">,</span> callback<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p>render方法就做了两件事，创建rootContainer和根据reconciler更新container。它接收的第三个参数是可选回调，这里不需要。</p>\n<p>我们写的这些配置项防止页面报错，也是告诉reconciler引入这些函数。我们使用mutation模式，以便目标（例如DOM）UI API支持UI树的更新（像appendChild, removeChild的操作等）。</p>\n<p>目前页面上还是空白的，下面是见证奇迹的时刻。为createInstance、createTextInstance、appendInitialChild、appendChildToContainer增加渲染逻辑:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token function-variable function\">createInstance</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">(</span>\n    <span class=\"token parameter\">type<span class=\"token punctuation\">,</span>\n    props<span class=\"token punctuation\">,</span>\n    rootContainerInstance<span class=\"token punctuation\">,</span>\n    hostContext<span class=\"token punctuation\">,</span>\n    internalInstanceHandle</span>\n<span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> document<span class=\"token punctuation\">.</span><span class=\"token function\">createElement</span><span class=\"token punctuation\">(</span>type<span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n<span class=\"token function-variable function\">createTextInstance</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">(</span>\n    <span class=\"token parameter\">text<span class=\"token punctuation\">,</span>\n    rootContainerInstance<span class=\"token punctuation\">,</span>\n    hostContext<span class=\"token punctuation\">,</span>\n    internalInstanceHandle</span>\n<span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> document<span class=\"token punctuation\">.</span><span class=\"token function\">createTextNode</span><span class=\"token punctuation\">(</span>text<span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n<span class=\"token function-variable function\">appendInitialChild</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">parent<span class=\"token punctuation\">,</span> child</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n    parent<span class=\"token punctuation\">.</span><span class=\"token function\">appendChild</span><span class=\"token punctuation\">(</span>child<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n<span class=\"token function-variable function\">appendChildToContainer</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">container<span class=\"token punctuation\">,</span> child</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n    container<span class=\"token punctuation\">.</span><span class=\"token function\">appendChild</span><span class=\"token punctuation\">(</span>child<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span></code></pre></div>\n<ul>\n<li>createInstance用于根据目标创建UI元素实例</li>\n<li>createTextInstance用于创建文本节点，因为DOM Target是使用独立的文本节点创建文本的，所以我们需要它</li>\n<li>appendInitialChild用于初始化UI树的创建</li>\n<li>appendChildToContainer在React-Reconciler的Commit阶段被调用（这里可想象成git的分支commit操作）</li>\n</ul>\n<p>可以看到页面上，文本节点已经被渲染出来了。但是我们的图片元素没有展示，a标签链接功能失效。基于上述描述，修改createInstance：</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token function-variable function\">createInstance</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">(</span>\n    <span class=\"token parameter\">type<span class=\"token punctuation\">,</span>\n    props<span class=\"token punctuation\">,</span>\n    rootContainer<span class=\"token punctuation\">,</span>\n    hostContext<span class=\"token punctuation\">,</span>\n    internalInstanceHandle</span>\n<span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">const</span> el <span class=\"token operator\">=</span> document<span class=\"token punctuation\">.</span><span class=\"token function\">createElement</span><span class=\"token punctuation\">(</span>type<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    Object<span class=\"token punctuation\">.</span><span class=\"token function\">keys</span><span class=\"token punctuation\">(</span>props<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">forEach</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">propName</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n        <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>propName <span class=\"token operator\">!==</span> <span class=\"token string\">'children'</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n            el<span class=\"token punctuation\">[</span>propName<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> props<span class=\"token punctuation\">[</span>propName<span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n        <span class=\"token punctuation\">}</span>\n        <span class=\"token keyword\">else</span> <span class=\"token punctuation\">{</span>\n          <span class=\"token comment\">// 打印一下children是什么</span>\n          console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>propName<span class=\"token punctuation\">,</span> props<span class=\"token punctuation\">[</span>propName<span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n        <span class=\"token punctuation\">}</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">return</span> el<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<ul>\n<li>当props不是children时，我们把props映射到元素上。包括alt、className、href、rel、src、target等，其中className会被react处理成class</li>\n<li>props是children时，我们打印出子树可以看到有host组件、文本等类型，由于文本已经被createTextInstance创建了节点，这里不用额外处理。</li>\n</ul>\n<p>为实例元素增加attribute之后，可以看到背景及图片都显示正常，我们的小目标也实现了。</p>\n<h3 id=\"动态显示logo\" style=\"position:relative;\"><a href=\"#%E5%8A%A8%E6%80%81%E6%98%BE%E7%A4%BAlogo\" aria-label=\"动态显示logo permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>动态显示Logo</h3>\n<p>接下来的工作是，通过点击class为App的DOM，使react logo动态显示。首先写我们的业务：</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token comment\">// App.js</span>\n    <span class=\"token operator\">...</span>\n    <span class=\"token keyword\">const</span> <span class=\"token punctuation\">[</span>showLogo<span class=\"token punctuation\">,</span> setShowLogo<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token function\">useState</span><span class=\"token punctuation\">(</span><span class=\"token boolean\">true</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">return</span> <span class=\"token punctuation\">(</span>\n        <span class=\"token operator\">&lt;</span>div className<span class=\"token operator\">=</span><span class=\"token string\">\"App\"</span> onClick<span class=\"token operator\">=</span><span class=\"token punctuation\">{</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n            <span class=\"token function\">setShowLogo</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">show</span> <span class=\"token operator\">=></span> <span class=\"token operator\">!</span>show<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n        <span class=\"token punctuation\">}</span><span class=\"token punctuation\">}</span><span class=\"token operator\">></span>\n            <span class=\"token operator\">&lt;</span>header className<span class=\"token operator\">=</span><span class=\"token string\">\"App-header\"</span><span class=\"token operator\">></span>\n                <span class=\"token punctuation\">{</span>showLogo <span class=\"token operator\">&amp;&amp;</span> <span class=\"token operator\">&lt;</span>img src<span class=\"token operator\">=</span><span class=\"token punctuation\">{</span>logo<span class=\"token punctuation\">}</span> className<span class=\"token operator\">=</span><span class=\"token string\">\"App-logo\"</span> alt<span class=\"token operator\">=</span><span class=\"token string\">\"logo\"</span> <span class=\"token operator\">/</span><span class=\"token operator\">></span><span class=\"token punctuation\">}</span>\n    <span class=\"token operator\">...</span></code></pre></div>\n<p>点击却发现onClick没有反应，说明我们刚才只赋值了静态属性，没有添加事件监听。在createInstance添加以下逻辑:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>propName <span class=\"token operator\">===</span> <span class=\"token string\">'onClick'</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    el<span class=\"token punctuation\">.</span><span class=\"token function\">addEventListener</span><span class=\"token punctuation\">(</span><span class=\"token string\">'click'</span><span class=\"token punctuation\">,</span> props<span class=\"token punctuation\">[</span>propName<span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span>\n<span class=\"token keyword\">else</span> <span class=\"token punctuation\">{</span>\n    el<span class=\"token punctuation\">[</span>propName<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> props<span class=\"token punctuation\">[</span>propName<span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>满心欢喜的点了一下页面以为everything under control了，结果。。。\n<img src=\"//images.ctfassets.net/49fdbwmpdowy/2FvoJn52wrvyFknULPEirW/f367201b0d80abf697121d181c9e5f98/5628dd6ecd9fa100f371_size30_w521_h534.jpg\" alt=\"size200\"></p>\n<p>！！！控制台报错了，查看以下API我们发现，需要配置dom remove及insert的module。</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token function-variable function\">removeChildFromContainer</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">container<span class=\"token punctuation\">,</span> child</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n    container<span class=\"token punctuation\">.</span><span class=\"token function\">removeChild</span><span class=\"token punctuation\">(</span>child<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n<span class=\"token function-variable function\">removeChild</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">parent<span class=\"token punctuation\">,</span> child</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n    parent<span class=\"token punctuation\">.</span><span class=\"token function\">removeChild</span><span class=\"token punctuation\">(</span>child<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n<span class=\"token function-variable function\">insertInContainerBefore</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">container<span class=\"token punctuation\">,</span> child<span class=\"token punctuation\">,</span> before</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n    container<span class=\"token punctuation\">.</span><span class=\"token function\">insertBefore</span><span class=\"token punctuation\">(</span>child<span class=\"token punctuation\">,</span> before<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n<span class=\"token function-variable function\">insertBefore</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">parent<span class=\"token punctuation\">,</span> child<span class=\"token punctuation\">,</span> before</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n    parent<span class=\"token punctuation\">.</span><span class=\"token function\">insertBefore</span><span class=\"token punctuation\">(</span>child<span class=\"token punctuation\">,</span> before<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span></code></pre></div>\n<p>四个模块都比较好理解，包含container的是commit阶段触发的行为。又实现了一个小目标。</p>\n<h3 id=\"使自定义props工作\" style=\"position:relative;\"><a href=\"#%E4%BD%BF%E8%87%AA%E5%AE%9A%E4%B9%89props%E5%B7%A5%E4%BD%9C\" aria-label=\"使自定义props工作 permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>使自定义props工作</h3>\n<p>最后一个任务是，用一个自定义属性控制p标签的背景色定时切换，我们还是先写简单的业务逻辑：</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token comment\">// App.js</span>\n<span class=\"token operator\">...</span>\n<span class=\"token keyword\">const</span> <span class=\"token punctuation\">[</span>color<span class=\"token punctuation\">,</span> setColor<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token function\">useState</span><span class=\"token punctuation\">(</span><span class=\"token string\">'red'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token function\">useEffect</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">const</span> colors <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span><span class=\"token string\">'red'</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'green'</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'blue'</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">let</span> i <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">const</span> interval <span class=\"token operator\">=</span> <span class=\"token function\">setInterval</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n        i<span class=\"token operator\">++</span><span class=\"token punctuation\">;</span>\n        <span class=\"token function\">setColor</span><span class=\"token punctuation\">(</span>colors<span class=\"token punctuation\">[</span>i <span class=\"token operator\">%</span> <span class=\"token number\">3</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span> <span class=\"token number\">1000</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">return</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token function\">clearInterval</span><span class=\"token punctuation\">(</span>interval<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token operator\">...</span>\n<span class=\"token operator\">&lt;</span>p bgColor<span class=\"token operator\">=</span><span class=\"token punctuation\">{</span>color<span class=\"token punctuation\">}</span><span class=\"token operator\">></span>\n    Edit <span class=\"token operator\">&lt;</span>code<span class=\"token operator\">></span>src<span class=\"token operator\">/</span>App<span class=\"token punctuation\">.</span>js<span class=\"token operator\">&lt;</span><span class=\"token operator\">/</span>code<span class=\"token operator\">></span> and save to reload<span class=\"token punctuation\">.</span>\n<span class=\"token operator\">&lt;</span><span class=\"token operator\">/</span>p<span class=\"token operator\">></span>\n<span class=\"token operator\">...</span></code></pre></div>\n<p>要完成这个任务，我们需要两个新的module，prepareUpdate和commitUpdate：</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token function-variable function\">prepareUpdate</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">(</span>\n    <span class=\"token parameter\">instance<span class=\"token punctuation\">,</span>\n    type<span class=\"token punctuation\">,</span>\n    oldProps<span class=\"token punctuation\">,</span>\n    newProps<span class=\"token punctuation\">,</span>\n    rootContainerInstance<span class=\"token punctuation\">,</span>\n    currentHostContext</span>\n<span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">let</span> payload<span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>oldProps<span class=\"token punctuation\">.</span>bgColor <span class=\"token operator\">!==</span> newProps<span class=\"token punctuation\">.</span>bgColor<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n        payload <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span>newBgColor<span class=\"token operator\">:</span> newProps<span class=\"token punctuation\">.</span>bgColor<span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span>\n    <span class=\"token keyword\">return</span> payload<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n<span class=\"token function-variable function\">commitUpdate</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">(</span>\n    <span class=\"token parameter\">instance<span class=\"token punctuation\">,</span>\n    updatePayload<span class=\"token punctuation\">,</span>\n    type<span class=\"token punctuation\">,</span>\n    oldProps<span class=\"token punctuation\">,</span>\n    newProps<span class=\"token punctuation\">,</span>\n    finishedWork</span>\n<span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>updatePayload<span class=\"token punctuation\">.</span>newBgColor<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n        instance<span class=\"token punctuation\">.</span>style<span class=\"token punctuation\">.</span>backgroundColor <span class=\"token operator\">=</span> updatePayload<span class=\"token punctuation\">.</span>newBgColor<span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<ul>\n<li>prepareUpdate用于diff元素的oldProps和newProps。在这里，当bgColor的props变化时，我们硬编码了一个新的props叫newBgColor</li>\n<li>commitUpdate用于随后更新实例props，这里当有newBgColor时，就将它赋予backgroundColor。</li>\n</ul>\n<h2 id=\"总结\" style=\"position:relative;\"><a href=\"#%E6%80%BB%E7%BB%93\" aria-label=\"总结 permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>总结</h2>\n<p>到这里我们就依赖fiber-reconciler完成了一个mini版本的ReactDOM的render操作，仔细想想我们还是有很多功能没有实现，例如form controls、refs、svg、portals、事件冒泡等。要想用好fiber-reconciler的module，需要理解currentTree和workInProgressTree，render阶段和commit阶段，感兴趣的同学可以接下来自己深入研究。</p>\n<p>附上ReactDOMMini不到100行的全部代码，去掉了没用到的参数：</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token comment\">/**\n * @file ReactDOMMini.js\n * @create date 2019-10-30 15:53:15\n * @modify date 2019-10-31 15:15:29\n */</span>\n<span class=\"token keyword\">import</span> reactReconciler <span class=\"token keyword\">from</span> <span class=\"token string\">'react-reconciler'</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">const</span> hostConfig <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token comment\">/* 宿主环境配置 */</span>\n    supportsMutation<span class=\"token operator\">:</span> <span class=\"token boolean\">true</span><span class=\"token punctuation\">,</span>\n    <span class=\"token function-variable function\">getRootHostContext</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n    <span class=\"token function-variable function\">prepareForCommit</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n    <span class=\"token function-variable function\">resetAfterCommit</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n    <span class=\"token function-variable function\">getChildHostContext</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n    <span class=\"token function-variable function\">shouldSetTextContent</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n    <span class=\"token function-variable function\">finalizeInitialChildren</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n    <span class=\"token function-variable function\">createInstance</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">(</span>\n        <span class=\"token parameter\">type<span class=\"token punctuation\">,</span>\n        props</span>\n    <span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n        <span class=\"token keyword\">const</span> el <span class=\"token operator\">=</span> document<span class=\"token punctuation\">.</span><span class=\"token function\">createElement</span><span class=\"token punctuation\">(</span>type<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n        Object<span class=\"token punctuation\">.</span><span class=\"token function\">keys</span><span class=\"token punctuation\">(</span>props<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">forEach</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">propName</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n            <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>propName <span class=\"token operator\">!==</span> <span class=\"token string\">'children'</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n                <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>propName <span class=\"token operator\">===</span> <span class=\"token string\">'onClick'</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n                    el<span class=\"token punctuation\">.</span><span class=\"token function\">addEventListener</span><span class=\"token punctuation\">(</span><span class=\"token string\">'click'</span><span class=\"token punctuation\">,</span> props<span class=\"token punctuation\">[</span>propName<span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n                <span class=\"token punctuation\">}</span>\n                <span class=\"token keyword\">else</span> <span class=\"token punctuation\">{</span>\n                    el<span class=\"token punctuation\">[</span>propName<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> props<span class=\"token punctuation\">[</span>propName<span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n                <span class=\"token punctuation\">}</span>\n            <span class=\"token punctuation\">}</span>\n        <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n        <span class=\"token keyword\">return</span> el<span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n    <span class=\"token function-variable function\">createTextInstance</span><span class=\"token operator\">:</span> <span class=\"token parameter\">text</span> <span class=\"token operator\">=></span> document<span class=\"token punctuation\">.</span><span class=\"token function\">createTextNode</span><span class=\"token punctuation\">(</span>text<span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n    <span class=\"token function-variable function\">appendInitialChild</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">parent<span class=\"token punctuation\">,</span> child</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n        parent<span class=\"token punctuation\">.</span><span class=\"token function\">appendChild</span><span class=\"token punctuation\">(</span>child<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n    <span class=\"token function-variable function\">appendChildToContainer</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">container<span class=\"token punctuation\">,</span> child</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n        container<span class=\"token punctuation\">.</span><span class=\"token function\">appendChild</span><span class=\"token punctuation\">(</span>child<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n    <span class=\"token function-variable function\">removeChildFromContainer</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">container<span class=\"token punctuation\">,</span> child</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n        container<span class=\"token punctuation\">.</span><span class=\"token function\">removeChild</span><span class=\"token punctuation\">(</span>child<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n    <span class=\"token function-variable function\">removeChild</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">parent<span class=\"token punctuation\">,</span> child</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n        parent<span class=\"token punctuation\">.</span><span class=\"token function\">removeChild</span><span class=\"token punctuation\">(</span>child<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n    <span class=\"token function-variable function\">insertInContainerBefore</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">container<span class=\"token punctuation\">,</span> child<span class=\"token punctuation\">,</span> before</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n        container<span class=\"token punctuation\">.</span><span class=\"token function\">insertBefore</span><span class=\"token punctuation\">(</span>child<span class=\"token punctuation\">,</span> before<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n    <span class=\"token function-variable function\">insertBefore</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">parent<span class=\"token punctuation\">,</span> child<span class=\"token punctuation\">,</span> before</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n        parent<span class=\"token punctuation\">.</span><span class=\"token function\">insertBefore</span><span class=\"token punctuation\">(</span>child<span class=\"token punctuation\">,</span> before<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n    <span class=\"token function-variable function\">prepareUpdate</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">(</span>\n        <span class=\"token parameter\">instance<span class=\"token punctuation\">,</span>\n        type<span class=\"token punctuation\">,</span>\n        oldProps<span class=\"token punctuation\">,</span>\n        newProps</span>\n    <span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n        <span class=\"token keyword\">let</span> payload<span class=\"token punctuation\">;</span>\n        <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>oldProps<span class=\"token punctuation\">.</span>bgColor <span class=\"token operator\">!==</span> newProps<span class=\"token punctuation\">.</span>bgColor<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n            payload <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span>newBgColor<span class=\"token operator\">:</span> newProps<span class=\"token punctuation\">.</span>bgColor<span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n        <span class=\"token punctuation\">}</span>\n        <span class=\"token keyword\">return</span> payload<span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n    <span class=\"token function-variable function\">commitUpdate</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">(</span>\n        <span class=\"token parameter\">instance<span class=\"token punctuation\">,</span>\n        updatePayload<span class=\"token punctuation\">,</span></span>\n    <span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n        <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>updatePayload<span class=\"token punctuation\">.</span>newBgColor<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n            instance<span class=\"token punctuation\">.</span>style<span class=\"token punctuation\">.</span>backgroundColor <span class=\"token operator\">=</span> updatePayload<span class=\"token punctuation\">.</span>newBgColor<span class=\"token punctuation\">;</span>\n        <span class=\"token punctuation\">}</span>\n    <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">const</span> reconciler <span class=\"token operator\">=</span> <span class=\"token function\">reactReconciler</span><span class=\"token punctuation\">(</span>hostConfig<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">export</span> <span class=\"token keyword\">default</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token function\">render</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">reactElement<span class=\"token punctuation\">,</span> domEle<span class=\"token punctuation\">,</span> callback</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n        <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">!</span>domEle<span class=\"token punctuation\">.</span>_rootContainer<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n            domEle<span class=\"token punctuation\">.</span>_rootContainer <span class=\"token operator\">=</span> reconciler<span class=\"token punctuation\">.</span><span class=\"token function\">createContainer</span><span class=\"token punctuation\">(</span>domEle<span class=\"token punctuation\">,</span> <span class=\"token boolean\">false</span><span class=\"token punctuation\">,</span> <span class=\"token boolean\">false</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n        <span class=\"token punctuation\">}</span>\n        reconciler<span class=\"token punctuation\">.</span><span class=\"token function\">updateContainer</span><span class=\"token punctuation\">(</span>reactElement<span class=\"token punctuation\">,</span> domEle<span class=\"token punctuation\">.</span>_rootContainer<span class=\"token punctuation\">,</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">,</span> callback<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span></code></pre></div>\n<h2 id=\"相关资料\" style=\"position:relative;\"><a href=\"#%E7%9B%B8%E5%85%B3%E8%B5%84%E6%96%99\" aria-label=\"相关资料 permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>相关资料</h2>\n<ol>\n<li><a href=\"https://www.youtube.com/watch?v=UxoX2faIgDQ\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">React Conf</a></li>\n<li><a href=\"https://github.com/facebook/react/tree/master/packages/react-reconciler\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">React Reconciler</a></li>\n<li><a href=\"https://reactjs.org/docs/codebase-overview.html#fiber-reconciler\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Fiber Reconciler</a></li>\n<li><a href=\"https://github.com/reactjs/react-art\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">React ART</a></li>\n<li><a href=\"https://medium.com/@agent_hunt/hello-world-custom-react-renderer-9a95b7cd04bc\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">hello-world-custom-react-renderer</a></li>\n</ol>","fields":{"slug":"/利用fiber-reconciler实现简易的reactdom-render操作/"},"tableOfContents":"<ul>\n<li><a href=\"//#reconciler%E4%BD%9C%E7%94%A8\">Reconciler作用</a></li>\n<li>\n<p><a href=\"//#%E5%AE%9E%E7%8E%B0reactdommini\">实现ReactDOMMini</a></p>\n<ul>\n<li><a href=\"//#%E6%B8%B2%E6%9F%93%E5%9F%BA%E7%A1%80%E8%A7%86%E5%9B%BE\">渲染基础视图</a></li>\n<li><a href=\"//#%E5%8A%A8%E6%80%81%E6%98%BE%E7%A4%BAlogo\">动态显示Logo</a></li>\n<li><a href=\"//#%E4%BD%BF%E8%87%AA%E5%AE%9A%E4%B9%89props%E5%B7%A5%E4%BD%9C\">使自定义props工作</a></li>\n</ul>\n</li>\n<li><a href=\"//#%E6%80%BB%E7%BB%93\">总结</a></li>\n<li><a href=\"//#%E7%9B%B8%E5%85%B3%E8%B5%84%E6%96%99\">相关资料</a></li>\n</ul>","frontmatter":{"id":"74bbb2a4a5074a0aa182511e12c2d7ef","description":"Fiber Reconciler是React 16默认的协调器，它抽象了宿主平台的特征，以实现不同的渲染需求。\n笔者最近在看React Conf，发现一个很有意思的demo，跟大家一起分享一下。","title":"利用fiber-reconciler实现简易的ReactDOM render操作","slug":"/","date":"2019年10月31日","tags":["React Conf","React Fiber"],"headerImage":"https://2img.net/h/i968.photobucket.com/albums/ae170/laughingjacky/Blog%20Assets%202019/react-fiber_zpstvbw5mlw.jpg"}},"previous":null,"next":null}]},"site":{"siteMetadata":{"title":"王晓博 - 银河系漫游指南","description":"如果这个博客好久不更新了,说明我更浑浑噩噩了"}}},"pageContext":{"id":"1eb0b1ed-515c-5154-b2c8-c8bf9824a42f","index":2}},"staticQueryHashes":[]}