Typescript 2.8 允许你基于单个文件来设置特定的 JSX 工厂函数名字。在这之前,你只能通过 --jsxFactory
编译选项来设置 JSX 工厂函数。并且这个设置会应用到整个项目中的所有 JSX 文件。现在,你可以通过在文件的开头添加特殊的 @jsx
注释来覆盖全局的 --jsxFactory
设置。
比方说我们想要使用 Preact
来将字符串 Hello, World!
渲染到 <div id="app">
容器中。因为 Preact 使用 h
函数来创建一个 JSX 元素,所以我们可以在文件的开头添加特殊的 /** @jsx */
注释(也被称作"pragma"):
/** @jsx h */
import { h, render } from "preact";
render(<h1>Hello World!</h1>, document.getElementById("app")!);
添加了 /** @jsx h */
之后,编译器会生成下面的代码:
/** @jsx h */
import { h, render } from "preact";
render(h("h1", null, "Hello World!"), document.getElementById("app"));
下面是我用来编译以上代码的 tsconfig.json
文件:
{
"compilerOptions": {
"target": "es5",
"module": "es2015",
"moduleResolution": "node",
"jsx": "react",
"strict": true
}
}
注意你只有使用 /** ... */
这种形式的注释风格编译器才能够识别出来。如果你使用 //...
这种单行注释语法,JSX 工厂函数的设置不会有任何改变。
JSX 不是 ECMAScript 标准的一部分,也就是说,它本身不是有效的 Javascript 代码。如果一个脚本或者模块包含了 JSX,它就不能直接在浏览器中运行。就如一个包含了类型标注的文件,JSX 文件也需要先编译成普通的 JavaScript 文件。--jsxFactory
选项告诉了 Typescript 编译器它该如何编译 JSX 元素。
留意 <h1>Hello World!</h1>
是如何被转换成 h("h1", null, "Hello World!")
的。Preact 使用了 h
函来创建虚拟 DOM 元素,这就是为什么我们设定 h
为 JSX 工厂函数名。我们同时需要从 preact
包中导入 h
,因为它会在模块中被使用。
所以我们什么时候需要基于文件粒度来设置 JSX 工厂函数呢?如果你项目中只使用一种 Javascript 库来处理 JSX,你并不需要按文件设置。在这种场景下,只需要修改 tsconfig.json
文件中的 --jsxFactory
选项即可,它会应用到你项目中的所有 JSX 文件:
{
"compilerOptions": {
"target": "es5",
"module": "es2015",
"moduleResolution": "node",
"jsx": "react",
"jsxFactory": "h",
"strict": true
}
}
默认情况下,如果使用 --jsx react
选项,--jsxFactory
会设置为 React.createElement
。因此,如果你使用 React,你不需要显式地设置 --jsxFactory
,也不需要添加 /** @jsx ... */
注释。
如果你在一个项目中会使用多个库来处理 JSX,那么按文件设置工厂函数就非常有用了。举个例子,你也许想在一个主要以 React 开发的应用中添加一个 Vue 组件,你可以在对应的文件顶部添加 /** @jsx ... */
来设置不同的 JSX 工厂函数,而不用使用多个 tsconfig.json
文件。