详解 TypeScript 编译 TSX 文件

一、简介

因为使用 Cycle.js 的 Vite + TSX 所以想详细的探索 TSX 在 TS 配置中的编译情况,本文主要讲解 tsconfig 和 tsx 编译与配置。以常见的框架 PReact 的虚拟 DOM + TSX 组合、snabbdom + TSX 组合不同的配置以及编译输出。

除了 TS 还可以渲染, babel 等编译器进行编译。

二、配置项目

配置选项 描述 示例配置
"jsx" 指定 JSX 的处理方式 "jsx": "react"
"jsxFactory" 指定在 JSX 中使用的工厂函数 "jsxFactory": "h"
"jsxFragmentFactory" 指定在 JSX 中使用的碎片工厂函数 "jsxFragmentFactory": "Fragment"
"jsxImportSource" 指定从哪个模块导入 JSX 相关的符号 "jsxImportSource": "react"
"reactNamespace" 指定全局变量或模块的命名空间,用于 React "reactNamespace": "myReact"
"jsxMode" 指定 JSX 模式,仅在 TypeScript 4.1+ 中可用 "jsxMode": "react"

例如: Preact 提供了自己的渲染函数 h, 用来渲染组件,此时就对应着 jsxFactory 配置项。

三、配置文件和命令行的优先级问题

  • 命令行参数优先级
  • 配置文件优先级

例如: jsx 标识符在命令行中使用 --jsx react 会覆盖 jsx: react-jsx

四、JSX 标识

1) 没有标识符

没有标识符时候,不支持编译 TSX/JSX 文件。

2)preserve 标识符

默认会将 TSX 文件装换成 JSX 文件, 其他的 JSX 结构没有改变

3)react/react-native 标识符

默认会使用 React.createElement 来创建元素,输出 js 文件,可以与 jsxFactory 工厂函数替换库中的函数

4)react-jsx/react-jsxdev

会使用相关 React 的 jsx-runtime 进行编译,也可以使用自定义 jsx-runtime 运行时。

五、PReact 虚拟dom 和 JSX

1) 写法一: 使用 preact 运行时

json 复制代码
{
    "jsx": "react-jsx",
    "jsxImportSource": "preact",
}

得到的编译结果是:

ts 复制代码
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const jsx_runtime_1 = require("preact/jsx-runtime");
function Card({ title, children }) {
    return ((0, jsx_runtime_1.jsxs)("div", { class: "card", children: [(0, jsx_runtime_1.jsx)("h1", { children: title }), children] }));
}

使用 preact 的 jsx 运行时。

2) 写法二: 使用 preact 提供的渲染函数 h 进行渲染

json 复制代码
{
    "jsx": "react",
    "jsxFactory": "h",  
}

得到的编译结果是:

ts 复制代码
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const preact_1 = require("preact");
function Card({ title, children }) {
    return ((0, preact_1.h)("div", { class: "card" },
        (0, preact_1.h)("h1", null, title),
        children));
}
;

使用 preact 的渲染函数 h。

六、snabbdom 与 @herp-inc/snabbdom-jsx

1)写法一:使用 jsx

ts 复制代码
{
    "jsx": "react-jsx",
    "jsxImportSource": "@herp-inc/snabbdom-jsx",
}

编译结果

ts 复制代码
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const jsx_runtime_1 = require("@herp-inc/snabbdom-jsx/jsx-runtime");
// import { jsx } from '@herp-inc/snabbdom-jsx'
const EventComp = () => {
    return (0, jsx_runtime_1.jsx)("div", { children: "sdfdsfdd" });
};
exports.default = EventComp;

使用 jsx 的运行时

2) 写法: jsx 使用

ts 复制代码
{
    "jsx": "react", 
    "jsxFactory": "jsx",
    "jsxFragmentFactory": "Fragment", 
}

编译的结果:

ts 复制代码
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const snabbdom_jsx_1 = require("@herp-inc/snabbdom-jsx");
const EventComp = () => {
    return (0, snabbdom_jsx_1.jsx)("div", null, "sdfdsfdd");
};
exports.default = EventComp;

使用@herp-inc/snabbdom-jsx内部实现的 jsx 函数。

七、snabbdom-jsx

没有运行时:snabbdom-jsx/jsx-runtime 所以不能使用 jsx 运行时编译

1)写法一

ts 复制代码
{
    "jsx": "react", 
    "jsxFactory": "html", 
}

组件写法以及编译后的写法

ts 复制代码
import { html } from 'snabbdom-jsx';

export const vnode = <div>Hello JSX</div>


"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.vnode = void 0;
const snabbdom_jsx_1 = require("snabbdom-jsx");
exports.vnode = (0, snabbdom_jsx_1.html)("div", null, "Hello JSX");

本质是使用了 snabbdom-jsx 提供的 html函数,源码如下:

ts 复制代码
module.exports = {
  html: JSX(undefined),
  svg: JSX(SVGNS, 'attrs'),
  JSX: JSX
};

小结

本文的主要目的是讲解 TS 中编译配置和在不同的环境下编译不同的 JSX/TSX 文件,由于 React 的JSX 实现了 jsx-runtime,所以基本上都有两套编译路径。若不了解 TSX 编译,本文可以很好的说明。其次可以使用 babel 等其他的工具进行编译学习。Cycle.js 中使用 snabbdom 作为虚拟 dom, 可以使用 TSX 不优雅的虚拟 dom 的写法。

相关推荐
蓝莓味的口香糖2 分钟前
【vue】初始化 Vue 项目
前端·javascript·vue.js
光影少年36 分钟前
数组去重方法
开发语言·前端·javascript
我命由我1234536 分钟前
浏览器的 JS 模块化支持观察记录
开发语言·前端·javascript·css·html·ecmascript·html5
weixin_443478511 小时前
Flutter第三方常用组件包之路由管理
前端·javascript·flutter
武藤一雄1 小时前
C# 异步回调与等待机制
前端·microsoft·设计模式·微软·c#·.netcore
啥都不懂的小小白1 小时前
前端CSS入门详解
前端·css
2601_949816162 小时前
spring.profiles.active和spring.profiles.include的使用及区别说明
java·后端·spring
林恒smileZAZ2 小时前
前端大屏适配方案:rem、vw/vh、scale 到底选哪个?
开发语言·前端·css·css3
QQ5110082852 小时前
基于区块链的个人医疗咨询挂号信息系统vue
前端·vue.js·区块链
helx823 小时前
SpringBoot实战(三十二)集成 ofdrw,实现 PDF 和 OFD 的转换、SM2 签署OFD
spring boot·后端·pdf