Vue3定义组件的四种方式

 更新时间:2025年03月04日 08:43:56   作者:前端大卫  
Vue 作为一款流行的前端框架,提供了多种方式来定义组件,包括单文件组件、渲染函数、、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

特点:

  • 需要引入 hdefineComponent 函数,没有模板语法。
  • 适合动态组件或 UI 库开发。

h 是一个 helper 函数,用于创建虚拟 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>
  );
};

优点:

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

缺点:

  • 不能在组件内部使用 refreactive,状态必须是全局变量或 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定义组件的资料请关注脚本之家其它相关文章!

相关文章

  • vue项目打包自动更新版本号且自动刷新缓存的方法示例

    vue项目打包自动更新版本号且自动刷新缓存的方法示例

    这篇文章主要给大家介绍了关于vue项目打包自动更新版本号且自动刷新缓存的相关资料,文中通过代码及图文介绍的非常详细,对大家学习或者使用vue具有一定的参考借鉴价值,需要的朋友可以参考下
    2024-11-11
  • 解决vue+router路由跳转不起作用的一项原因

    解决vue+router路由跳转不起作用的一项原因

    这篇文章主要介绍了解决vue+router路由跳转不起作用的一项原因,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-07-07
  • vue部署后静态文件加载404的解决

    vue部署后静态文件加载404的解决

    这篇文章主要介绍了vue部署后静态文件加载404的解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-04-04
  • vue项目页面的打印和下载PDF加loading效果的实现(加水印)

    vue项目页面的打印和下载PDF加loading效果的实现(加水印)

    这篇文章主要介绍了vue项目页面的打印和下载PDF加loading效果的实现(加水印),具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-12-12
  • 详解vue-router 路由元信息

    详解vue-router 路由元信息

    本篇文章主要介绍了vue-router 路由元信息,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-09-09
  • vue 清空input标签 中file的值操作

    vue 清空input标签 中file的值操作

    这篇文章主要介绍了vue 清空input标签 中file的值操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-07-07
  • 浅谈element中InfiniteScroll按需引入的一点注意事项

    浅谈element中InfiniteScroll按需引入的一点注意事项

    这篇文章主要介绍了浅谈element中InfiniteScroll按需引入的一点注意事项,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-06-06
  • 深入理解vue路由的使用

    深入理解vue路由的使用

    vue-router是Vue.js官方的路由插件,它和vue.js是深度集成的,适合用于构建单页面应用。
    2017-03-03
  • Vue项目部署上线全过程记录(保姆级教程)

    Vue项目部署上线全过程记录(保姆级教程)

    vue项目开发完毕后,我们需要将项目打包上线,同时我们希望可以在本地预览生产环境项目,下面这篇文章主要给大家介绍了关于Vue项目部署上线的相关资料,需要的朋友可以参考下
    2023-03-03
  • Vue3+TypeScript+Vite服务端渲染项目的实现

    Vue3+TypeScript+Vite服务端渲染项目的实现

    本文主要介绍了Vue3+TypeScript+Vite服务端渲染项目的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2025-09-09

最新评论