1.什么是 jsx
jsx 是 js 代码,通过编译转换成虚拟 dom 节点。
- JSX 是一个
JavaScript的语法扩展,JSX 可以很好地描述 UI 应该呈现出它应有交互的本质形式
react17 版本以前的转义,
注意:需要在文件头引入 react
import React from 'react'
2. classic模式和automatic模式生成的结构对比
a) classic模式转换的jsx
const babel = require("@babel/core");
const sourceCode = `
<h1>
hello<span style={{ color: 'red' }}>world</span>
</h1>
`;
const result = babel.transform(sourceCode, {
plugins: [["@babel/plugin-transform-react-jsx", { runtime: "classic" }]],
});
// 生成的代码
React.createElement(
"h1",
null,
"hello",
React.createElement(
"span",
{
style: {
color: "red",
},
},
"world"
)
);
b)automatic模式转换的jsx
react 17 以后的转义, 转换后不需要在手动引入 react,运行时会加载runtime文件
const babel = require("@babel/core");
const sourceCode = `
<h1>
hello<span style={{ color: 'red' }}>world</span>
</h1>
`;
const result = babel.transform(sourceCode, {
plugins: [["@babel/plugin-transform-react-jsx", { runtime: "automatic" }]],
});
// automatic模式生成的代码,是用jsx方法来处理了,最终还是调用ReactElement生成虚拟dom
import { jsx as _jsx } from "react/jsx-runtime";
import { jsxs as _jsxs } from "react/jsx-runtime";
/*#__PURE__*/
_jsxs("h1", {
children: [
"hello",
/*#__PURE__*/ _jsx("span", {
style: {
color: "red",
},
children: "world",
}),
],
});
// jsx和jsxs对应的方法,最终都是调用jsxDEV方法去做一些参数校验和props处理,然后创建react元素,虚拟dom
var jsx = jsxWithValidationDynamic; // we may want to special case jsxs internally to take advantage of static children.
// for now we can ship identical prod functions
var jsxs = jsxWithValidationStatic;
function jsxDEV(type, config, maybeKey, source, self) {
{
var propName; // Reserved names are extracted
var props = {};
var key = null;
var ref = null;
if (maybeKey !== undefined) {
{
checkKeyStringCoercion(maybeKey);
}
key = "" + maybeKey;
}
if (hasValidKey(config)) {
{
checkKeyStringCoercion(config.key);
}
key = "" + config.key;
}
if (hasValidRef(config)) {
ref = config.ref;
warnIfStringRefCannotBeAutoConverted(config, self);
} // 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];
}
} // Resolve default props
// 前面的都是做一些校验和处理props,这里去创建虚拟dom
return ReactElement(
type,
key,
ref,
self,
source,
ReactCurrentOwner.current,
props
);
}
}
// element就是虚拟dom,react node。
var ReactElement = function (type, key, ref, self, source, owner, props) {
var element = {
// This tag allows us to uniquely identify this as a React Element
$$typeof: REACT_ELEMENT_TYPE,
// Built-in properties that belong on the element
type: type, //元素标签span,h1等
key: key, //唯一标识
ref: ref,
props: props, //属性 children,style,id
// Record the component responsible for creating this element.
_owner: owner,
};
return element;
};
浏览器运行时加载 jsx-dev-runtime.js,提供 jsxDev 方法.
- React17以前老版的转换函数中key 是放在config里的,第三个参数放children
- React17之后新版的转换函数中key是在第三个参数中的,children是放在config里的
无论是新版还是旧版最终都会调用
ReactElement最终返回虚拟 DOM
开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 2天,点击查看活动详情