共计 1731 个字符,预计需要花费 5 分钟才能阅读完成。
参考 React 官网文档、https://www.jianshu.com/p/8dc…
JSX
JSX 是一个 JavaScript 的语法扩大,在 HTML 模板中嵌入 JavaScript 语法。因为 React 认为组件渲染逻辑与 UI 视图存在外在耦合,而 JSX 能够很好地形容 UI 应该呈现出它应有交互的实质模式,所以 React 倡议应用 JSX 语法。JSX 齐全能够实现 JavaScript 原有的性能。
JSX 实质是 React.createElement 的语法糖,如下图例子所示,JSX 会被 Babel 编译为 createElement 函数调用
createElement()
ReactElement 中 createElement() 是这样定义的 `
function createElement(type,config,children)
调用 createElement 办法返回一个蕴含类型、属性、子节点的对象,这个对象称为 React 元素 , 也就是 React vdom 的节点
virtual dom 是 React 性能优化的重要点,实质是 JS 对象,所有节点以键值对模式存在,节点也是 JS 对象,用嵌套模式示意 dom 的树形构造。
那么 createElement 办法具体做了什么事呢?
- 首先遍历 config 参数也就是节点的属性,保留在 props 对象中
- 把 children 参数封装成数组,保留在 props 对象中
- 依据 type 参数判断节点默认属性,将默认属性也保留在 props 对象
- 最初调用 ReactElement 办法并传入 type、props,返回一个对象
ReactElement 办法返回的对象长这样
- $$typeof 属性用于检测节点是否为非法的 React 元素
- type 属性即节点类型
- key 用作节点的惟一标识
- ref 用于获取实在的 dom 节点
- props 蕴含了节点的默认属性和用户给它定义的属性以及子节点
- _owner 标识该节点隶属于哪个组件
ReactDom.render
createElement 创立的 React 元素是怎么渲染到页面的呢?ReactDom 为用户提供了 render 办法渲染元素。
ReactDOM.render(element, container[, callback])
在提供的 container
里渲染一个 React 元素,并返回对该组件的援用(或者针对无状态组件返回 null
)。
如果 React 元素之前曾经在 container
里渲染过,这将会对其执行更新操作,并仅会在必要时扭转 DOM 以映射最新的 React 元素。
如果提供了可选的回调函数,该回调将在组件被渲染或更新之后被执行。
在理论我的项目中,所有组件作为子节点渲染到 id 为 root 的 div 容器
留神
ReactDOM.render()
会管制你传入容器节点里的内容。当首次调用时,容器节点里的所有 DOM 元素都会被替换,后续的调用则会应用 React 的 DOM 差分算法(DOM diffing algorithm)进行高效的更新。ReactDOM.render()
不会批改容器节点(只会批改容器的子节点)。能够在不笼罩现有子节点的状况下,将组件插入已有的 DOM 节点中。ReactDOM.render()
目前会返回对根组件ReactComponent
实例的援用。然而,目前应该防止应用返回的援用,因为它是历史遗留下来的内容,而且在将来版本的 React 中,组件渲染在某些状况下可能会是异步的。如果你真的须要取得对根组件ReactComponent
实例的援用,那么举荐为根元素增加 callback ref。- 应用
ReactDOM.render()
对服务端渲染容器进行 hydrate 操作的形式曾经被废除,并且会在 React 17 被移除。作为代替,请应用hydrate()
。
为了防止每次计算 dom 节点差别时递归遍历 dom 树的操作,React 团队给出了 React Fiber 算法以及 fiber tree 数据结构(基于单链表的树结构),而 render 办法就是实现 React Fiber 算法以及构建 fiber tree 的外围 API。对于这部分的实现,请参考结尾链接。
总结
总而言之,React 渲染的过程实际上是由 JSX 创立 React 元素作为虚构 dom 节点,调用 render 办法创立一棵 dom 树
对于 vdom 改天再写一篇具体的总结