初始化
jsx —经过babel转换—> createElement(创建vdom)——> render(vdom -> 真实dom)
更新
state/props改变 ——> update(diff…) ——> render(vdom -> 真实dom)
React渲染的过程实际上是由JSX创建React元素作为虚拟dom节点,调用render方法创建一棵虚拟dom树,然后映射到真实dom上由浏览器渲染出来。state和props改变时,会再次调用render生成一棵新的虚拟dom树,通过diff算法计算新旧两棵虚拟dom的差异,再异渲染到真实dom上
JSX
JSX是一个 JavaScript 的语法扩展,在HTML模板中嵌入JavaScript语法。由于React认为组件渲染逻辑与UI视图存在内在耦合,而JSX 可以很好地描述UI应该呈现出它应有交互的本质形式,所以React建议使用JSX语法。JSX完全可以实现JavaScript原有的功能。
JSX本质是React.createElement的语法糖,如下图例子所示,JSX会被Babel编译为createElement函数调用
createElement
实现转义后的jsx渲染到浏览器页面
挂载是递归过程
function createElement(type, props, ...children) {return {type,props: {...props,children: children.map((child) =>typeof child === "object" ? child : createTextElement(child)),},};}function createTextElement(text) {return {type: "TEXT_ELEMENT",props: {nodeValue: text,children: [],},};}function render(element, container) {const dom =element.type == "TEXT_ELEMENT"? document.createTextNode(""): document.createElement(element.type);const isProperty = (key) => key !== "children";Object.keys(element.props).filter(isProperty).forEach((name) => {dom[name] = element.props[name];});// 一旦我们开始渲染,我们不会停止,直到我们渲染了完整的元素树。// 如果元素树很大,可能会阻塞主线程太久。如果浏览器需要做高优先级的事情,// 比如处理用户输入或保持动画流畅,它必须等到渲染完成。element.props.children.forEach((child) => render(child, dom));container.appendChild(dom);}const Didact = {createElement,render,};// https://stackoverflow.com/questions/53803466/what-does-the-comment-jsx-jsx-do-in-the-emotion-css-in-js-library// 这是一个自定义 pragma,它告诉 jsx 转换器,在这种情况下,babel-plugin-transform-react 使用什么函数将您的 jsx 转换为纯 javascript。/** @jsx Didact.createElement */const element = (<div style="background: red"><h1>Hello World</h1><h2 style="text-align:right">from Didact</h2></div>);const el = document.getElementById("root");Didact.render(element, el);
存在问题
一旦我们开始渲染,我们不会停止,直到我们渲染了完整的元素树。如果元素树很大,可能会阻塞主线程太久。如果浏览器需要做高优先级的事情,比如处理用户输入或保持动画流畅,它必须等到渲染完成。
react完整的createElement

- $$typeof属性用于检测节点是否为合法的React元素
- type属性即节点类型
- key用作节点的唯一标识
- ref用于获取真实的dom节点
- props包含了节点的默认属性和用户给它定义的属性以及子节点
- _owner标识该节点隶属于哪个组件
