原文自定义jsx解析工厂函数
问题
我们通常会在react项目中使用jsx,当我们习惯了jsx的语法之后,可能就脱离不开jsx了,如果我们不在react而是在一个原生js项目中也想使用jsx怎么办呢?
解决方案
react官方已经出了一个新的jsx解析器,剥离了jsx-runtime用来单独解析jsx,可以脱离react使用jsx,并且和babel、typescript官方合作,使用babel或者ts配置即可解析jsx,都提供了简洁的配置方案。或者,我们还可以自定义一个jsx解析函数。
方案一:Babel配置
- 先安装依赖包
npm update @babel/core @babel/preset-react
- 再配置
babel.config.json
文件
{
"presets": [
["@babel/preset-react", {
"runtime": "automatic"
}]
]
}
方案二:typescript配置
要在ts中使用jsx,即使用tsx。Typescript 4.1 支持 React 17的jsx和jsxs工厂函数的tsconfig.json
配置
- 开发环境下用
"jsx":"react-jsxdev"
- 生产环境下用
"jsx":"react-jsx"
比如:
// ./src/tsconfig.json
{
"compilerOptions": {
"module": "esnext",
"target": "es2015",
"jsx": "react-jsx",
"strict": true
},
"include": [
"./**/*"
]
}
方案三:自定义tsx工厂函数
自定义一套jsx解析工厂函数,可以了解jsx的解析过程。下面演示一个ts版本的tsx解析函数。
- 先定义一个
jsxFactory.ts
用作定义和导出工厂函数
// --- jsxFactory.ts ---
/* https://gist.github.com/borestad/eac42120613bc67a3714f115e8b485a7
* Custom jsx parser
* See: tsconfig.json
*
* {
* "jsx": "react",
* "jsxFactory": "h",
* "lib": [
* "es2017",
* "dom",
* "dom.iterable"
* ]
* }
*
*/
interface entityMapData {
[key: string]: string;
}
export const entityMap: entityMapData = {
"&": "amp",
"<": "lt",
">": "gt",
'"': "quot",
"'": "#39",
"/": "#x2F",
};
export const escapeHtml = (str: object[] | string) =>
String(str).replace(/[&<>"'\/\\]/g, (s) => `&${
entityMap[s]};`);
// To keep some consistency with React DOM, lets use a mapper
// https://reactjs.org/docs/dom-elements.html
export const AttributeMapper = (val: string) =>
({
tabIndex: "tabindex",
className: "class",
readOnly: "readonly",
}[val] || val);
// tslint:disable-next-line:no-default-export
export function DOMcreateElement(