Vue3定义组件的四种方式:SFC、渲染函数、JSX与函数式组件对比

作者:星野

时间:2026-10-31

浏览:124

本文深入解析Vue3中定义组件的四种核心方式:单文件组件(SFC)、渲染函数、JSX/TSX以及函数式组件。详细对比了各方式在代码结构、开发体验、性能表现及适用场景上的差异,帮助开发者根据项目需求选择最合适的组件定义方案。

文章目录

背景

Vue 作为主流前端框架,支持多种组件定义模式,涵盖单文件组件 (SFC)、渲染函数 (Render Functions)、JSX/TSX 及函数式组件 (Functional Components)。各模式适配不同场景,选型需权衡可读性、性能与灵活性。本文深入对比这四种方式,辅助开发者制定最佳项目方案。

1. SFC (Single-File Component)

单文件组件采用 *.vue 扩展名,获 Vue 官方首选推荐。

特性:

  • 模板与逻辑解耦,架构清晰,获官方背书。
  • 兼容 Vue 原生特性,包括 script setup、CSS 作用域及单文件热更新等。
  • 契合主流 Vue 项目,代码组织直观易懂。

Test.vue 示例代码如下:

<script setup lang="ts">
import { ref } from "vue";
defineProps<{
  text: string;
}>();

const num = ref(0);
</script>
<template>
  <div class="aaa">
    {{ text }}
    <div @click="num++">{{ num }}</div>
  </div>
</template>

优势:

  • 结构明晰,契合 MVVM 范式,模板部分易读性强。
  • script setup 提供精简语法,降低模板与逻辑间的切换成本。
  • 拥有完善的工具链生态 (Vue 官方、Vite、Vue Loader 等)。

局限:

  • 依赖构建工具 (如 Vite 或 Webpack) 编译,无法直接在浏览器执行。
  • 特定场景 (如动态创建组件) 灵活性不及渲染函数。

2. 渲染函数 (Render Functions)

Vue 提供 h() 函数以生成虚拟节点 vnodes。

特性:

  • 需引入 h 与 defineComponent 函数,摒弃模板语法。
  • 适用于动态组件或 UI 库构建。

h 为辅助函数,用于创建虚拟 DOM (VNode),系 createElement 别名,类比 React 的 React.createElement。

Test.ts 示例代码:

import { defineComponent, h, ref } from "vue";

export default defineComponent({
  props: {
    text: {
      type: String,
      required: true
    }
  },
  setup(props) {
    const num = ref(0);
    return () =>
      h("div", { class: "aaa" }, [props.text, h("div", { onClick: () => num.value++ }, num.value)]);
  }
});

优势:

  • 灵活性高,适用于需动态控制 VNode 结构的场景,如表单渲染器、可拖拽组件等。
  • 体积更小,无需 SFC 解析器。

局限:

  • 可读性较差,无模板语法,复杂组件维护成本高。
  • 开发体验逊于 SFC,尤其对不熟悉 JSX/TSX 的开发者。

3. JSX / TSX

JSX 与 TSX 源自 React 语法扩展,Vue 亦支持。

特性:

  • 语法类 React,允许在 Vue 组件中使用 JSX/TSX。
  • 适用于灵活逻辑处理,无需引入 h() 函数。

tsconfig.json 需配置:

{
  "compilerOptions": {
    "jsx": "preserve",
    "jsxImportSource": "vue"
    // ...
  }
}

vite.config.ts 需配置 vueJsx 插件:

import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";
import vueJsx from "@vitejs/plugin-vue-jsx";

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

Test.tsx 示例代码:

import { defineComponent, ref } from "vue";

export default defineComponent({
  props: {
    text: {
      type: String,
      required: true
    }
  },
  setup(props) {
    const num = ref(0);
    return () => (
      <div class="aaa">
        {props.text}
        <div onClick={() => num.value++}>{num.value}</div>
      </div>
    );
  }
});

优势:

  • 代码灵活,适用于复杂 UI 组件开发。
  • TypeScript 项目中类型推导支持更佳。

局限:

  • 需额外 @vitejs/plugin-vue-jsx 插件支持,并在 tsconfig.json 配置 JSX 选项。
  • 风格背离 Vue 传统模板语法,可能不适配所有团队。

4. 函数式组件 (Functional Components) — 不推荐

特性:

  • 组件本质为纯函数,ref 仅能定义于组件外部,属全局共享状态。
  • 适用于仅依赖 props 渲染且无状态 (stateless) 的组件。

Test.tsx 示例代码:

import { ref, type FunctionalComponent } from "vue";

interface Props {
  text: string;
}

const num = ref(0);
export const TestFunctionalCom: FunctionalComponent<Props> = (props) => {
  return (
    <div class="aaa">
      {props.text}
      <div onClick={() => num.value++}>{num.value}</div>
    </div>
  );
};

优势:

  • 代码简洁,适用于简单展示组件 (如按钮、图标等)。
  • 无响应式数据追踪开销,性能更优。

局限:

  • 组件内部不可使用 ref 或 reactive,状态须为全局变量或 props 传入。
  • 全局 ref 可能导致多组件实例共享状态,引发意外状态同步问题。

总结

方式适用场景优点缺点
SFC (单文件组件)适用于大多数 Vue 项目结构清晰、官方推荐、支持 script setup需要构建工具
渲染函数 (Render Functions)适用于动态组件/UI 库代码更灵活,适用于动态 VNode 结构可读性较低,维护成本高
JSX / TSX适用于复杂逻辑组件代码灵活,可与 TypeScript 结合需要额外配置,不符合 Vue 传统语法
函数式组件适用于无状态小组件代码简单、性能较高不能使用 ref,全局状态共享有风险

实际开发中,SFC 为首选方案,多数 Vue 组件可借由 SFC 实现。涉及动态 VNode 结构时,可考虑渲染函数或 JSX/TSX。函数式组件在 Vue 3 中场景稀缺,通常不建议使用。

以上为 Vue3 定义组件的四种方式详解,更多 Vue3 定义组件资料请关注本站其他相关文章!

实用工具推荐

电子包浆

绿化、压缩、噪点和虚拟水印,自由调节做旧程度。

使用 ›
图片压缩

选择画质和输出格式,预览压缩前后的大小。

使用 ›
相关文章