什么是 jsx

jsxJavaScript 的一个类似 XML 的扩展, 可以使用js的语法编写 HTML 的结构,并使用babel的编译工具进行转译,转换成常规的js实现后续的渲染

jsx 和 template 如何选择

  1. jsx 可以支持更动态的需求。而 template 则因为语法限制原因,不能够像jsx 那样可以支持更动态的需求。这是 jsx 相比于 template 的一个优势。

  2. template 牺牲灵活性换来了静态标记的收益:
    就是重复执行 render 的时候,比如,代码里的 h1 这个纯静态的标签,就不需要进行额外地计算,并且静态标签在 虚拟DOM 计算的时候,会直接越过 Diff 过程,这也是 Vue 3 的虚拟DOM 能够比 Vue 2 快的一个重要原因。

  3. 我们实现业务需求的时候,也是优先使用 template,动态性要求较高的组件使用 jsx 实现

  4. jsxtemplate渲染 20000 个dom

    • template性能方面快点
    • jsx 初始化的时候快点

准备工作

  • vue-cli工程项目默认支持jsx,无需额外配置
  • 基于vite2.x使用jsx
    1. 安装pnpm install @vitejs/plugin-vue-jsx
    2. vite.config.js配置如下
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      import { defineConfig, loadEnv } from 'vite'
      import vue from '@vitejs/plugin-vue'
      import vueJsx from '@vitejs/plugin-vue-jsx'
      const resolve = dir=>path.join(__dirname,dir);
      export default ({mode})=>{
      return defineConfig({
      ...
      plugins:[
      vueJsx(),
      ]
      })
      }
    3. tsconfig.json 配置如下
      1
      2
      3
      4
      5
      6
      {
      "compilerOptions":{
      ...
      "jsx":"preserve"
      }
      }

jsx 写法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
import { defineComponent, ref } from 'vue'
import type { PropType } from 'vue'
import { Button } from 'vant'
type Todo = {
name: string
id: number
}
/**tsx写法示例 */
export default defineComponent({
props: {
todo: {
type: Object as PropType<Todo>,
required: true
},
name: {
type: String,
required: false
}
},
emits: ['click'],
setup(props, { emit, slots }) {
const list = ref([1, 2, 3])
const renderTitle = (str: string) => <div>{str}</div>
const renderFooter = () => {
return (
<div class="class" onClick={v => handleClick(v)}>
脚部
</div>
)
}
const handleClick = val => {
console.log(val)
}
//<></>默认容器 类似template 不会渲染真实dom
return () => (
<>
<div class="jsx-demo">
<div>jsx示例写法</div>
{renderTitle('函数执行')}
<Button
onClick={() => emit('click')}
v-slots={{
default: () => slots.default?.() || 'jsx默认插槽写法'
}}
/>
<Button>{slots.default?.() || '插槽'}</Button>
{/* 列表渲染 */}
{list.value.map(v => (
<div>{v}</div>
))}
{/* 不能在这里使用if else 采用三元表达式,复杂场景用函数 */}
{true ? <div>true</div> : <div>false</div>}
{renderFooter()}
</div>
</>
)
}
})