元件
應用是一棵元件樹:父元件負責排版與資料流,子元件負責一塊 UI。溝通的基本規則是 props 往下、事件往上、插槽把版面留給父層。官方:Components Basics。
使用子元件
<script setup>
import UserCard from './UserCard.vue'
</script>
<template>
<UserCard name="Ada" :age="36" @select="onSelect" />
</template>
<script setup> 裡 import 的元件可以直接用在樣板,不必再註冊。
props:父傳子
子元件宣告會收到什麼:
<script setup>
defineProps({
name: { type: String, required: true },
age: { type: Number, default: 0 },
})
</script>
<template>
<p>{{ name }}({{ age }})</p>
</template>
TypeScript 專案可用 defineProps<{ name: string; age?: number }>()。
Props 是單向的:子元件不要直接改 prop。要改,請 emit 事件讓父層改自己的狀態,或把值複製到本地 ref。
emits:子傳父
<script setup>
const emit = defineEmits(['select'])
function onClick() {
emit('select', { id: 1 })
}
</script>
父層用 @select="handler" 接。事件名建議用 kebab-case(item-select)。表單類元件可用 v-model,底層是 modelValue prop 加上 update:modelValue 事件;Vue 3.4 起也可用 defineModel()。
slots:把版面交給父層
<!-- Card.vue -->
<template>
<article class="card">
<header><slot name="header" /></header>
<slot>預設內容</slot>
</article>
</template>
沒寫 name 的是預設插槽。作用域插槽(scoped slot)能讓子元件把資料傳回插槽,父層再決定怎麼渲染,適合表格列、下拉選項。
拆元件的尺度
一塊 UI 出現第二次、或單檔已經難掃讀,就拆。不要為了「看起來元件化」把每一行按鈕都做成檔案。資料盡量留在真正擁有它的那一層,用 props/emits 傳遞,避免到處 provide/inject(那是跨很多層的進階手段)。
跨頁狀態見 Pinia。把邏輯抽出去重用,見 Composables。
推薦影音
Vue 組件結構:基本觀念和語法
來源:彭彭的課程
繁中講為什麼要拆元件、父層怎麼引入子元件。同一播放清單接著是 自訂屬性 與 自訂事件,對應本頁 props/emits。