React.createElement参数执行机制、组件顺序及/*#__PURE__*/含义咨询
React组件执行顺序与Babel编译标记疑问解答
问题背景
用户编写的React组件代码:
const COMP = () => { return ( <> <h1>IN COMP</h1> {console.log("in comp")} </> ); }; const App = () => { return ( <> <COMP /> <h1>IN APP</h1> {console.log("in app")} </> ); };
经Babel编译后的代码:
const Comp = () => { return /*#__PURE__*/React.createElement(/*#__PURE__*/React.Fragment, null, /*#__PURE__*/React.createElement("h1", null, "IN COMP"), console.log("in comp")); } const App = () => { return /*#__PURE__*/React.createElement(/*#__PURE__*/React.Fragment, null, /*#__PURE__*/React.createElement("h1", null, "IN APP"), /*#__PURE__*/React.createElement(Comp, null), console.log("in app")); }
用户预期控制台输出顺序为 in comp → in app,但实际输出顺序是 in app → in comp,由此提出两个疑问:
- React是否会暂停子组件执行,优先执行其他JS代码?想了解这段代码的实际执行流程。
/*#__PURE__*/的含义是什么?子元素不是以列表形式传递的吗?
疑问解答
1. 代码实际执行流程
React并没有暂停子组件执行,核心原因是子组件函数的执行时机和父组件里的同步代码不同:
- 当
App组件函数被调用时,会先执行return语句里的React.createElement调用。JS的函数调用规则是:所有参数会先被依次求值,再传入函数。- 第一步:求值
React.createElement("h1", null, "IN APP"),生成h1对应的React元素对象(无输出)。 - 第二步:求值
React.createElement(Comp, null),这里只是生成一个指向Comp组件的元素对象,不会执行Comp组件函数(无输出)。 - 第三步:求值
console.log("in app"),直接在控制台输出in app。 - 最后把这些求值结果作为参数,创建Fragment元素对象返回。
- 第一步:求值
- 当React开始渲染这个Fragment元素时,才会遍历它的子元素:遇到
Comp对应的元素时,才会调用Comp组件函数。此时Comp函数内部的代码执行:- 求值
React.createElement("h1", null, "IN COMP")(无输出)。 - 求值
console.log("in comp"),输出in comp。 - 返回
Comp的Fragment元素对象。
- 求值
所以实际输出顺序是in app先出现,之后才是in comp。
2. /*#__PURE__*/的含义与子元素传递
/*#__PURE__*/的作用:这是Babel为Tree Shaking工具(如Terser)添加的特殊注释,用来标记当前的React.createElement调用是纯函数调用——即调用这个函数不会产生副作用(比如修改全局变量、发起请求),返回值只依赖传入的参数。如果这段代码对应的元素最终没有被渲染到页面上,Tree Shaking可以安全地删除这段代码,减少打包后的体积。- 子元素的传递方式:
React.createElement的第三个及之后的所有参数都是子元素,React内部会自动把这些参数收集成数组(即props.children),不需要开发者手动写成数组形式。Babel编译JSX时,会把JSX里的每个子节点依次作为参数传给React.createElement,React会统一处理成数组或单个元素。
内容的提问来源于stack exchange,提问作者Prajval Gahine
相关产品推荐
相关产品推荐

