What is JSX?
Official definition: JSX
is React.createElement(components, props, ...children)
Syntax sugar for functions
<Mybutton color="blue" shadowSize={2}>
Click Me
</Mybutton>
The above function will be compiled to the following code:
React.createElement(
Mybutton,
{color: 'blue', shadowSize: 2},
'Click Me'
)
Open the source code of React and find the createElement
function:
function createElement(type, config, children) {
var propName; // Reserved names are extracted
var props = {};
var key = null;
var ref = null;
var self = null;
var source = null;
if (config != null) {
if (hasValidRef(config)) {
ref = config.ref;
{
warnIfStringRefCannotBeAutoConverted(config);
}
}
if (hasValidKey(config)) {
{
checkKeyStringCoercion(config.key);
}
key = '' + config.key;
}
self = config.__self === undefined ? null : config.__self;
source = config.__source === undefined ? null : config.__source; // Remaining properties are added to a new props object
for (propName in config) {
if (hasOwnProperty.call(config, propName) && !RESERVED_PROPS.hasOwnProperty(propName)) {
props[propName] = config[propName];
}
}
} // Children can be more than one argument, and those are transferred onto
// the newly allocated props object.
var childrenLength = arguments.length - 2;
if (childrenLength === 1) {
props.children = children;
} else if (childrenLength > 1) {
var childArray = Array(childrenLength);
for (var i = 0; i < childrenLength; i++) {
childArray[i] = arguments[i + 2];
}
{
if (Object.freeze) {
Object.freeze(childArray);
}
}
props.children = childArray;
} // Resolve default props
if (type && type.defaultProps) {
var defaultProps = type.defaultProps;
for (propName in defaultProps) {
if (props[propName] === undefined) {
props[propName] = defaultProps[propName];
}
}
}
{
if (key || ref) {
var displayName = typeof type === 'function' ? type.displayName || type.name || 'Unknown' : type;
if (key) {
defineKeyPropWarningGetter(props, displayName);
}
if (ref) {
defineRefPropWarningGetter(props, displayName);
}
}
}
return ReactElement(type, key, ref, self, source, ReactCurrentOwner.current, props);
}
From the source code, we can see createElement
function receives three parameters: type (label type), config (attribute in label), children (sublabel)
However, when writing JSX
, a tag usually contains multiple subtags, so how does the function receive these subtags?
We focus on this part of the source code:
var childrenLength = arguments.length - 2;
if (childrenLength === 1) {
props.children = children;
} else if (childrenLength > 1) {
var childArray = Array(childrenLength);
for (var i = 0; i < childrenLength; i++) {
childArray[i] = arguments[i + 2];
}
{
if (Object.freeze) {
Object.freeze(childArray);
}
}
props.children = childArray;
} // Resolve default props
We know that the arguments object contains all parameters, then childrenLength is the number of remaining parameters excluding the first two parameters
If childrenLength is 1, there is only one child element (can be text or new JSX) If childrenLength is greater than 1, create an array of length childrenLength, and use a for loop to add the objects in arguments to the array
A simplified version of React.createElement
ReactElement
Object definition:
function ReactElement(type, key, props) {
return {
$$typeof: Symbol.for('react.element'),
type,
key,
props
}
}
createElement()
Function implementation:
function createElement(type, config, children) {
const props = {};
if (config) {
// 将 config 中的键值对添加到 props 中
for (propName in config) {
if (hasOwnProperty.call(config, propName)) {
props[propName] = config[propName];
}
}
}
const childrenLength = arguments.length - 2;
// 多个children使用数组的形式
if (childrenLength === 1) {
props.children = children;
} else if (childrenLength > 1) {
const childArray = Array(childrenLength);
for (let i = 0; i < childrenLength; i++) {
childArray[i] = arguments[2 + i];
}
props.children = childArray;
}
return ReactElement(type, null, props);
}
When there is only one DOM node, call the createElement function:
let a = createElement(
'div',
{width:'20px', height: '20px'},
)
prints out a, which results in:
{
'$$typeof': Symbol(react.element),
type: 'div',
key: null,
props: { width: '20px', height: '20px' }
}
Since there are no child elements, there is no children attribute in props
When the parent node has multiple child nodes:
let a = createElement(
'div',
{width:'20px', height: '20px'},
createElement(
'p'
),
createElement(
'a'
),
)
prints out a, which results in:
{
'$$typeof': Symbol(react.element),
type: 'div',
key: null,
props: { width: '20px', height: '20px', children: [ [Object], [Object] ] }
}
As you can see, when there are multiple child elements, children store these child elements in the form of an array.
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。