为什么新版本React可以忽略全局导入
- 很多时候,我们只写一个纯组件,并没有用到React的一些api,但是仍然需要在模块中导入React
- 而不导入会报错,
React找不到
const App = () => {
return (
<h1>
hello<span style={{ color: "red" }}>world</span>
</h1>
);
};
export default App;
看起来没什么问题,为什么会报错
- 下载依赖:
npm i @babel/core @babel/plugin-transform-react-jsx -D
- 报错通常是在编译过程中产生的,我们使用babel编译看下
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" }]],
});
console.log(result.code);
- 可以看到编译完成,将我们的jsx语法转换成了React.createElement这种方式,
这个函数会返回虚拟dom
- 那么现在我们应该可以了解为什么会报错了,因为使用到了React上的createElement方法,而React并未引入,那么报错是理所当然的
如何使其在不导入的情况下也不报错
- 将上述例子中的
runtime
的值改为automatic
import { jsx as _jsx } from "react/jsx-runtime";
import { jsxs as _jsxs } from "react/jsx-runtime";
_jsxs("h1", {
children: ["hello", _jsx("span", {
style: {
color: 'red'
},
children: "world"
})]
});
- 可以看到,它将createElement转换成了jsx,且自动帮我们引入了jsx这个方法,所以不会出现找不到的情况
简单实现下jsx转义
- 源码目录:
- 在18中,将babel编译将key放到了第三个参数中
export { jsxDEV } from "./src/jsx/ReactJSXElement";
import { REACT_ELELEMT_TYPE } from "shared/ReactSymbols";
import hasOwnProperty from "shared/hasOwnProperty";
const RESERVED_PROPS = {
key: true,
ref: true,
__self: true,
__source: true,
};
function hasValidRef(config) {
return config.ref !== undefined;
}
function ReactElement(type, key, ref, props) {
return {
$$typeof: REACT_ELELEMT_TYPE,
type,
key,
ref,
props,
};
}
export function jsxDEV(type, config, maybeKey) {
let propName;
const props = {};
let key = null;
let ref = null;
if (maybeKey !== undefined) {
key = maybeKey;
}
if (hasValidRef(config)) {
ref = config.ref;
}
for (propName in config) {
if (
hasOwnProperty.call(config, propName) &&
!RESERVED_PROPS.hasOwnProperty(propName)
) {
props[propName] = config[propName];
}
}
return ReactElement(type, key, ref, props);
}