You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
jsx 都会被 babel 编译成 createElement 函数,该函数会创建一个 react element,一个 element 如下:
{// This tag allows us to uniquely identify this as a React Element$$typeof: REACT_ELEMENT_TYPE,// Built-in properties that belong on the elementtype: type,key: key,ref: ref,props: props,// Record the component responsible for creating this element._owner: owner,};
上文中 element 提到的 $$typeof 字段,还有如下类型:
REACT_ELEMENT_TYPE
REACT_PORTAL_TYPE
REACT_FRAGMENT_TYPE
REACT_STRICT_MODE_TYPE
REACT_PROFILER_TYPE
REACT_PROVIDER_TYPE
REACT_CONTEXT_TYPE
REACT_ASYNC_MODE_TYPE
REACT_CONCURRENT_MODE_TYPE
REACT_FORWARD_REF_TYPE
REACT_SUSPENSE_TYPE
以 ReactDOM.render(<App />, document.getElementById('container')) 为例,
type 值就为 一个 function App()。
type指代这个ReactElement的类型:
functionworkLoop(isYieldy){if(!isYieldy){// Flush work without yielding// 不可中断while(nextUnitOfWork!==null){nextUnitOfWork=performUnitOfWork(nextUnitOfWork);}}else{while(nextUnitOfWork!==null&&!shouldYieldToRenderer()){nextUnitOfWork=performUnitOfWork(nextUnitOfWork);}}}
本文基于 React 16.8.6 版本创作
React element
jsx 都会被 babel 编译成 createElement 函数,该函数会创建一个 react element,一个 element 如下:
上文中 element 提到的 $$typeof 字段,还有如下类型:
以
ReactDOM.render(<App />, document.getElementById('container'))
为例,type 值就为 一个
function App()
。type指代这个ReactElement的类型:
React 中的更新
让组件发生渲染,无非就是下列几种情况:
其他的一些 hook,在 React 内部对这种行为进行了抽象,为此 新起了一个机制,叫做 Update。
调用 setState,render 都会产生一个 Update ,一个 Update 如下所示
在上文中的
render(<App />)
, 就会创建一个更新,并且把 当前 App 组件当做 payload。伪代码如下:
Fiber
在上文中,还会为 App 创建对应的 Fiber 节点,创建完 Update,就会将该 Fiber 节点调度更新。
enqueueUpdate
为 FIber 节点添加一个 更新队列(updateQueue)的属性,为一个队列,专门存储上文提到的 一个个 Update。scheduleWork
先找到 fiber root,本文中即对应挂载节点,由于 第一次 render 会选取 performSyncWork,以同步的方式进行渲染,让用户以最快的时间看到内容。从顶层节点开始。不过,React 会略过已经处理过的 Fiber 节点,直到找到未完成工作的节点。例如,如果在组件树中的深层组件中调用 setState 方法,则 React 将从顶部开始,但会快速跳过各个父项,直到它到达调用了 setState 方法的组件。
performWorkOnRoot
设置 isRendering = true; 代表进入 render 阶段。
采用深度优先遍历,从上往下生成子 Fiber,这里也是大名鼎鼎的 work loop 在这进行循环单元更新。并且进行善后处理。
workLoop 如下,
这里这是一个循环处理的策略,
如果你不了解 workLoop,可以查看:https://stackblitz.com/edit/js-ntqfil?file=index.js,
此链接来源于译文:https://zhuanlan.zhihu.com/p/51483167。
beginWork 根据不同的组件执行不同的渲染,
向下遍历 JSX,为每个 JSX 节点的子 JSX 节点生成对应的 Fiber,并且记上一个 tag
commit 阶段
render 阶段有 2 棵树和副作用列表。第一个树表示当前在屏幕上渲染的状态,然后在 render 阶段会构建一个备用树。它在源代码中称为 finishedWork 或 workInProgress,表示需要映射到屏幕上的状态
我们已经知道哪些 Fiber 会打上 Fiber.effectTag, 插入、更新或删除的节点。
有了 effectList 就能渲染页面。
在 commit 阶段运行的主要函数是 commitRoot , 它会根据不同的 tag 执行不同的行为。
The text was updated successfully, but these errors were encountered: