1

参考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函数调用
JSX.png

createElement()

ReactElement中createElement()是这样定义的`

function createElement(type,config,children)

调用createElement方法返回一个包含类型、属性、子节点的对象,这个对象称为React元素,也就是React vdom的节点

virtual dom是React性能优化的重要点,本质是JS对象,所有节点以键值对形式存在,节点也是JS对象,用嵌套形式表示dom的树形结构。

那么createElement方法具体做了什么事呢?
createElement.png

  • 首先遍历config参数也就是节点的属性,保存在props对象中
  • 把children参数封装成数组,保存在props对象中
  • 根据type参数判断节点默认属性,将默认属性也保存在props对象
  • 最后调用ReactElement方法并传入type、props,返回一个对象

ReactElement方法返回的对象长这样
ReactElement.png

  • $$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树,然后映射到真实dom上由浏览器渲染出来。state和props改变时,会再次调用render生成一棵新的虚拟dom树,通过diff算法计算新旧两棵虚拟dom的差异,再异渲染到真实dom上

关于vdom改天再写一篇详细的总结


菜菜的电冰箱
15 声望0 粉丝

程序媛