Skip to content

JSX in Vue

在 vue 项目中使用 jsx 语法,快速创建虚拟 DOM,代替以 h 函数创建虚拟 DOM。

为什么需要 jsx?例如我们想要渲染一个这样的虚拟 DOM 结构:

js
{
  tags:'div',
  {
    onClick(){
      console.log('ok')
    }
  },
  children:[
    {
      tags:'div',
      children:'123'
    },
    {
      tags:'div',
      children:'456'
    }
  ]
}
{
  tags:'div',
  {
    onClick(){
      console.log('ok')
    }
  },
  children:[
    {
      tags:'div',
      children:'123'
    },
    {
      tags:'div',
      children:'456'
    }
  ]
}

使用 h 函数

js
h(
  "div",
  {
    onClick() {
      console.log("ok");
    },
  },
  [h("div", 123), h("div", 456)]
);
h(
  "div",
  {
    onClick() {
      console.log("ok");
    },
  },
  [h("div", 123), h("div", 456)]
);

使用 jsx

jsx
<div onClick={() => console.log("ok")}>
  <div>123</div>
  <div>456</div>
</div>
<div onClick={() => console.log("ok")}>
  <div>123</div>
  <div>456</div>
</div>

使用 jsx 就可以让我们在脚本里面写类似标签一样的语法,非常的舒服。

0.安装

shell
pnpm add @vitejs/plugin-vue-jsx -D
pnpm add @vitejs/plugin-vue-jsx -D

安装完成后在 vite 配置文件中安装插件

js
import vueJsx from "@vitejs/plugin-vue-jsx";

export default defineConfig({
  plugins: [vueJsx()],
});
import vueJsx from "@vitejs/plugin-vue-jsx";

export default defineConfig({
  plugins: [vueJsx()],
});

1.tsx 的插槽定义写法

slots 可以获取到使用组件时传入的插槽,每个 key 都是具名插槽(除了 default),其 value 为一个 render 函数,调用该函数即可获取一个虚拟 DOM,我们只需要让该虚拟 DOM 出现在对应位置即可。

tsx
// Son.tsx
export default defineComponent({
  setup(_, { slots }) {
    return () => (
      <div>
        {slots.default()}
        {slots.gender()}
        {slots.fullName()}
      </div>
    );
  },
});
// Son.tsx
export default defineComponent({
  setup(_, { slots }) {
    return () => (
      <div>
        {slots.default()}
        {slots.gender()}
        {slots.fullName()}
      </div>
    );
  },
});

2.tsx 的插槽传入写法

多个插槽

tsx
// Parent.tsx
import { defineComponent } from "vue";
import Son from "./Son";

export default defineComponent({
  setup() {
    return () => (
      <Son>
        {{
          default: () => 123,
          gender: () => <span>男</span>,
          fullName: () => [<span>Lebron</span>, <span>James</span>],
        }}
      </Son>
    );
  },
});
// Parent.tsx
import { defineComponent } from "vue";
import Son from "./Son";

export default defineComponent({
  setup() {
    return () => (
      <Son>
        {{
          default: () => 123,
          gender: () => <span>男</span>,
          fullName: () => [<span>Lebron</span>, <span>James</span>],
        }}
      </Son>
    );
  },
});

一个插槽

tsx
// Parent.tsx
import { defineComponent } from "vue";
import Son from "./Son";

export default defineComponent({
  setup() {
    return () => (
      <Son>
        <span>男</span>,
      </Son>
    );
  },
});
// Parent.tsx
import { defineComponent } from "vue";
import Son from "./Son";

export default defineComponent({
  setup() {
    return () => (
      <Son>
        <span>男</span>,
      </Son>
    );
  },
});

3.在 SFC 中编写 jsx

想要在 vue 文件中使用 jsx 语法,只需要在script标签的lang属性的值设置为jsxtsx即可。

vue
<script lang='tsx'><script>
<script lang='tsx'><script>