Vue 3 提供了对 JSX 语法的支持,使得我们可以在 Vue 项目中灵活使用 JSX 进行开发。JSX 是一种允许在 JavaScript 代码中直接写 HTML 结构的语法,在 React 中被广泛使用。通过本文,您将深入了解如何在 Vue 3 中使用 JSX 语法,涵盖多个示例和不同情况下的写法。

安装和配置

在 Vue 3 项目中使用 JSX 需要安装相关的 Babel 插件。可以通过以下命令进行安装:

npm install @vue/babel-plugin-jsx

然后在项目根目录下的 babel.config.js 文件中配置插件:

module.exports = {
  presets: ['@vue/cli-plugin-babel/preset'],
  plugins: ['@vue/babel-plugin-jsx']
};

基础示例

首先,让我们来看一个简单的例子,使用 JSX 语法创建一个 Vue 组件。

使用模板语法

<template>
  <div>
    <h1>{{ message }}</h1>
    <button @click="handleClick">Click Me</button>
  </div>
</template>

<script setup>
import { ref } from 'vue';

const message = ref('Hello Vue 3');

function handleClick() {
  message.value = 'Button Clicked';
}
</script>

使用 JSX 语法

<script setup lang="jsx">
import { ref } from 'vue';

const message = ref('Hello Vue 3');

function handleClick() {
  message.value = 'Button Clicked';
}
</script>

<template>
  {() => (
    <div>
      <h1>{message.value}</h1>
      <button onClick={handleClick}>Click Me</button>
    </div>
  )}
</template>

在 JSX 语法中,我们通过 {} 来插入表达式,onClick 用于绑定事件处理函数。

属性和事件

在 Vue 3 中,HTML 属性和事件绑定可以使用类似的方式在 JSX 中进行编写。

属性绑定

<template>
  <img :src="imageUrl" :alt="imageAlt" />
</template>

<script setup>
const imageUrl = 'https://example.com/image.jpg';
const imageAlt = 'Example Image';
</script>

在 JSX 中:

<script setup lang="jsx">
const imageUrl = 'https://example.com/image.jpg';
const imageAlt = 'Example Image';
</script>

<template>
  {() => (
    <img src={imageUrl} alt={imageAlt} />
  )}
</template>

事件绑定

<template>
  <button @click="handleClick">Click Me</button>
</template>

<script setup>
function handleClick() {
  console.log('Button Clicked');
}
</script>

在 JSX 中:

<script setup lang="jsx">
function handleClick() {
  console.log('Button Clicked');
}
</script>

<template>
  {() => (
    <button onClick={handleClick}>Click Me</button>
  )}
</template>

条件渲染和列表渲染

条件渲染

使用模板语法进行条件渲染:

<template>
  <div>
    <p v-if="isVisible">Visible Text</p>
    <p v-else>Hidden Text</p>
  </div>
</template>

<script setup>
import { ref } from 'vue';

const isVisible = ref(true);
</script>

在 JSX 中:

<script setup lang="jsx">
import { ref } from 'vue';

const isVisible = ref(true);
</script>

<template>
  {() => (
    <div>
      {isVisible.value ? <p>Visible Text</p> : <p>Hidden Text</p>}
    </div>
  )}
</template>

列表渲染

使用模板语法进行列表渲染:

<template>
  <ul>
    <li v-for="item in items" :key="item.id">{{ item.name }}</li>
  </ul>
</template>

<script setup>
import { ref } from 'vue';

const items = ref([
  { id: 1, name: 'Item 1' },
  { id: 2, name: 'Item 2' },
  { id: 3, name: 'Item 3' }
]);
</script>

在 JSX 中:

<script setup lang="jsx">
import { ref } from 'vue';

const items = ref([
  { id: 1, name: 'Item 1' },
  { id: 2, name: 'Item 2' },
  { id: 3, name: 'Item 3' }
]);
</script>

<template>
  {() => (
    <ul>
      {items.value.map(item => (
        <li key={item.id}>{item.name}</li>
      ))}
    </ul>
  )}
</template>

使用插槽

插槽是 Vue 中一个强大的功能,用于分发内容。我们也可以在 JSX 中使用插槽。

使用模板语法的插槽

<template>
  <BaseLayout>
    <template #header>
      <h1>Header Content</h1>
    </template>
    <template #default>
      <p>Main Content</p>
    </template>
    <template #footer>
      <p>Footer Content</p>
    </template>
  </BaseLayout>
</template>

在 JSX 中:

<script setup lang="jsx">
import BaseLayout from './BaseLayout.vue';
</script>

<template>
  {() => (
    <BaseLayout>
      {{
        header: () => <h1>Header Content</h1>,
        default: () => <p>Main Content</p>,
        footer: () => <p>Footer Content</p>
      }}
    </BaseLayout>
  )}
</template>

自定义指令

在 Vue 3 中,我们可以使用自定义指令。在 JSX 中使用自定义指令时,需要借助 v-directive

使用模板语法的自定义指令

<template>
  <input v-focus />
</template>

<script setup>
import { onMounted } from 'vue';

const vFocus = {
  mounted(el) {
    el.focus();
  }
};

app.directive('focus', vFocus);
</script>

在 JSX 中:

<script setup lang="jsx">
import { onMounted } from 'vue';

const vFocus = {
  mounted(el) {
    el.focus();
  }
};

app.directive('focus', vFocus);
</script>

<template>
  {() => (
    <input v-focus />
  )}
</template>

表单处理

在 Vue 3 中,表单处理是一个常见的任务。在 JSX 中,我们可以使用类似的方式处理表单数据。

使用模板语法的表单处理

<template>
  <div>
    <input v-model="name" placeholder="Enter your name" />
    <p>Your name is: {{ name }}</p>
  </div>
</template>

<script setup>
import { ref } from 'vue';

const name = ref('');
</script>

在 JSX 中:

<script setup lang="jsx">
import { ref } from 'vue';

const name = ref('');
</script>

<template>
  {() => (
    <div>
      <input v-model={name.value} placeholder="Enter your name" />
      <p>Your name is: {name.value}</p>
    </div>
  )}
</template>

动态组件

在 Vue 3 中,动态组件可以通过 <component> 标签实现。在 JSX 中,我们可以使用类似的方式来动态渲染组件。

使用模板语法的动态组件

<template>
  <component :is="currentComponent"></component>
</template>

<script setup>
import { ref } from 'vue';
import ComponentA from './ComponentA.vue';
import ComponentB from './ComponentB.vue';

const currentComponent = ref('ComponentA');

const components = {
  ComponentA,
  ComponentB
};
</script>

在 JSX 中:

<script setup lang="jsx">
import { ref, defineComponent } from 'vue';
import ComponentA from './ComponentA.vue';
import ComponentB from './ComponentB.vue';

const currentComponent = ref('ComponentA');

const components = {
  ComponentA,
  ComponentB
};
</script>

<template>
  {() => {
    const DynamicComponent = components[currentComponent.value];
    return <DynamicComponent />;
  }}
</template>

组合式 API 和 JSX

Vue 3 的组合式 API 提供了一种更加灵活和可重用的代码组织方式。在 JSX 中,我们同样可以利用组合式 API 来管理组件状态和逻辑。

使用模板语法的组合式 API

<template>
  <div>
    <p>{{ count }}</p>
    <button @click="increment">Increment</button>
  </div>
</template>

<script setup>
import { ref } from 'vue';

const count = ref(0);

function increment() {
  count.value++;
}
</script>

在 JSX 中:

<script setup lang="jsx">
import { ref } from 'vue';

const count = ref(0);

function increment() {
  count.value++;
}
</script>

<template>
  {() => (
    <div>
      <p>{count.value}</p>
      <button onClick={increment}>Increment</button>
    </div>
  )}
</template>

高阶组件

高阶组件(Higher-Order Components, HOC)是一种用于复用组件逻辑的技术。在 Vue 3 中,我们可以使用 JSX 来创建高阶组件。

使用模板语法的高阶组件

<template>
  <div>
    <slot></slot>
  </div>
</template>

<script setup>
const withLogger = (WrappedComponent) => {
  return {
    components: { WrappedComponent },
    setup() {
      console.log('Component rendered');
    }
  }
};
</script>

在 JSX 中:

<script setup lang="jsx">
import { defineComponent } from 'vue';

const withLogger = (WrappedComponent) => {
  return defineComponent({
    setup() {
      console.log('Component rendered');
    },
    render() {
      return <WrappedComponent />;
    }
  });
};
</script>

Naive UI 组件示例

Naive UI 是一个 Vue 3 的组件库,提供了丰富的 UI 组件。下面是一些使用 Naive UI 组件的示例。

安装 Naive UI

首先,安装 Naive UI:

npm install naive-ui

使用按钮组件

<script setup lang="jsx">
import { NButton } from 'naive-ui';

function handleClick() {
  console.log('Naive UI Button Clicked');
}
</script>

<template>
  {() => (
    <NButton onClick={handleClick}>Naive UI Button</NButton>
  )}
</template>

使用输入框组件

<script setup lang="jsx">
import { ref } from 'vue';
import { NInput } from 'naive-ui';

const inputText = ref('');
</script>

<template>
  {() => (
    <div>
      <NInput v-model:value={inputText.value} placeholder="Enter text" />
      <p>{inputText.value}</p>
    </div>
  )}
</template>

使用表格组件

<script setup lang="jsx">
import { ref } from 'vue';
import { NDataTable } from 'naive-ui';

const columns = [
  {
    title: 'Name',
    key: 'name'
  },
  {
    title: 'Age',
    key: 'age'
  }
];

const data = ref([
  { key: 1, name: 'John', age: 30 },
  { key: 2, name: 'Jane', age: 25 }
]);
</script>

<template>
  {() => (
    <NDataTable columns={columns} data={data.value} />
  )}
</template>

结论

本文详细介绍了在 Vue 3 中使用 JSX 语法的各种方法和注意事项。我们通过多个示例展示了如何在不同情况下使用 JSX 进行开发,包括属性绑定、事件处理、条件渲染、列表渲染、插槽、自定义指令、表单处理、动态组件、组合式 API 和高阶组件。此外,还展示了如何在 Vue 3 项目中配置 Naive UI 并使用其组件。希望这些内容能帮助你更好地理解和应用 JSX 语法,提升 Vue 3 开发的灵活性和效率。