Vue3定義組件的四種方式
背景
Vue 作為一款流行的前端框架,提供了多種方式來定義組件,包括單文件組件 (SFC)、渲染函數(shù) (Render Functions)、JSX/TSX 以及函數(shù)式組件 (Functional Components)。不同的方式適用于不同的場(chǎng)景,開發(fā)者在選擇時(shí)需要考慮可讀性、性能和靈活性等因素。本文將對(duì)這四種方式進(jìn)行詳細(xì)對(duì)比,幫助你找到最適合自己項(xiàng)目的方案。
1. SFC (Single-File Component)
單文件組件,以 *.vue 作為文件擴(kuò)展名,是 Vue 官方推薦的方式。
特點(diǎn):
- 模板和邏輯分離,結(jié)構(gòu)清晰,官方推薦。
- 支持 Vue 內(nèi)置功能,如
script setup、CSS 作用域、單文件組件熱更新等。 - 適合大多數(shù) Vue 項(xiàng)目,代碼組織更直觀。
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>
優(yōu)點(diǎn):
- 代碼結(jié)構(gòu)清晰,符合 MVVM 模式,模板部分易讀。
script setup提供更簡(jiǎn)潔的語法,減少模板和邏輯之間的代碼切換。- 具有良好的工具鏈支持 (Vue 官方生態(tài)、Vite、Vue Loader 等)。
缺點(diǎn):
- 需要額外的構(gòu)建工具 (如 Vite 或 Webpack) 進(jìn)行編譯,不能直接在瀏覽器運(yùn)行。
- 在某些場(chǎng)景下 (如動(dòng)態(tài)創(chuàng)建組件) 可能不如渲染函數(shù)靈活。
2. 渲染函數(shù) (Render Functions)
Vue 提供了一個(gè) h() 函數(shù)用于創(chuàng)建虛擬節(jié)點(diǎn) vnodes。
特點(diǎn):
- 需要引入
h和defineComponent函數(shù),沒有模板語法。 - 適合動(dòng)態(tài)組件或 UI 庫開發(fā)。
h 是一個(gè) helper 函數(shù),用于創(chuàng)建虛擬 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)]);
}
});
優(yōu)點(diǎn):
- 代碼更靈活,適用于需要?jiǎng)討B(tài)控制 VNode 結(jié)構(gòu)的場(chǎng)景,如表單渲染器、可拖拽組件等。
- 體積更小,不需要 SFC 解析器。
缺點(diǎn):
- 代碼可讀性較低,沒有模板語法,編寫復(fù)雜組件時(shí)維護(hù)成本較高。
- 開發(fā)體驗(yàn)不如 SFC 友好,特別是對(duì)于不熟悉 JSX/TSX 的開發(fā)者。
3. JSX / TSX
JSX 和 TSX 是 React 的語法擴(kuò)展,Vue 也支持這種語法。
特點(diǎn):
- 語法類似 React,允許在 Vue 組件中使用 JSX/TSX 語法。
- 適用于更靈活的邏輯處理,且無需引入
h()函數(shù)。
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>
);
}
});
優(yōu)點(diǎn):
- 代碼靈活,適用于復(fù)雜 UI 組件開發(fā)。
- 在 TypeScript 項(xiàng)目中擁有更好的類型推導(dǎo)支持。
缺點(diǎn):
- 需要額外的
@vitejs/plugin-vue-jsx插件支持,并在tsconfig.json配置 JSX 選項(xiàng)。 - 代碼風(fēng)格不符合 Vue 傳統(tǒng)的模板語法,可能不適合所有團(tuán)隊(duì)。
4. 函數(shù)式組件 (Functional Components) — 不推薦
特點(diǎn):
- 組件本質(zhì)上是一個(gè)純函數(shù),
ref只能定義在組件外部,屬于全局共享狀態(tài)。 - 適用于只依賴
props進(jìn)行渲染,且無狀態(tài) (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>
);
};
優(yōu)點(diǎn):
- 代碼簡(jiǎn)單,適用于簡(jiǎn)單的展示組件 (如按鈕、圖標(biāo)等)。
- 沒有響應(yīng)式數(shù)據(jù)追蹤開銷,性能更高。
缺點(diǎn):
- 不能在組件內(nèi)部使用
ref或reactive,狀態(tài)必須是全局變量或props傳入。 - 全局
ref可能導(dǎo)致多個(gè)組件實(shí)例共享狀態(tài),引發(fā)意外的狀態(tài)同步問題。
總結(jié)
| 方式 | 適用場(chǎng)景 | 優(yōu)點(diǎn) | 缺點(diǎn) |
|---|---|---|---|
| SFC (單文件組件) | 適用于大多數(shù) Vue 項(xiàng)目 | 結(jié)構(gòu)清晰、官方推薦、支持 script setup | 需要構(gòu)建工具 |
| 渲染函數(shù) (Render Functions) | 適用于動(dòng)態(tài)組件/UI 庫 | 代碼更靈活,適用于動(dòng)態(tài) VNode 結(jié)構(gòu) | 可讀性較低,維護(hù)成本高 |
| JSX / TSX | 適用于復(fù)雜邏輯組件 | 代碼靈活,可與 TypeScript 結(jié)合 | 需要額外配置,不符合 Vue 傳統(tǒng)語法 |
| 函數(shù)式組件 | 適用于無狀態(tài)小組件 | 代碼簡(jiǎn)單、性能較高 | 不能使用 ref,全局狀態(tài)共享有風(fēng)險(xiǎn) |
在實(shí)際開發(fā)中,SFC 是最推薦的方式,大多數(shù) Vue 組件都可以用 SFC 實(shí)現(xiàn)。對(duì)于動(dòng)態(tài) VNode 結(jié)構(gòu),可以考慮 渲染函數(shù) 或 JSX/TSX。函數(shù)式組件 在 Vue 3 中的使用場(chǎng)景很少,通常不推薦使用。
以上就是Vue3定義組件的四種方式的詳細(xì)內(nèi)容,更多關(guān)于Vue3定義組件的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
vue項(xiàng)目打包自動(dòng)更新版本號(hào)且自動(dòng)刷新緩存的方法示例
這篇文章主要給大家介紹了關(guān)于vue項(xiàng)目打包自動(dòng)更新版本號(hào)且自動(dòng)刷新緩存的相關(guān)資料,文中通過代碼及圖文介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用vue具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2024-11-11
解決vue+router路由跳轉(zhuǎn)不起作用的一項(xiàng)原因
這篇文章主要介紹了解決vue+router路由跳轉(zhuǎn)不起作用的一項(xiàng)原因,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-07-07
vue項(xiàng)目頁面的打印和下載PDF加loading效果的實(shí)現(xiàn)(加水印)
這篇文章主要介紹了vue項(xiàng)目頁面的打印和下載PDF加loading效果的實(shí)現(xiàn)(加水印),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-12-12
淺談element中InfiniteScroll按需引入的一點(diǎn)注意事項(xiàng)
這篇文章主要介紹了淺談element中InfiniteScroll按需引入的一點(diǎn)注意事項(xiàng),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-06-06
Vue項(xiàng)目部署上線全過程記錄(保姆級(jí)教程)
vue項(xiàng)目開發(fā)完畢后,我們需要將項(xiàng)目打包上線,同時(shí)我們希望可以在本地預(yù)覽生產(chǎn)環(huán)境項(xiàng)目,下面這篇文章主要給大家介紹了關(guān)于Vue項(xiàng)目部署上線的相關(guān)資料,需要的朋友可以參考下2023-03-03
Vue3+TypeScript+Vite服務(wù)端渲染項(xiàng)目的實(shí)現(xiàn)
本文主要介紹了Vue3+TypeScript+Vite服務(wù)端渲染項(xiàng)目的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2025-09-09

