Skip to content

建立 2026-09-15 更新 2026-09-15

元件

應用是一棵元件樹:父元件負責排版與資料流,子元件負責一塊 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>
<Card>
  <template #header>標題</template>
  正文
</Card>

沒寫 name 的是預設插槽。作用域插槽(scoped slot)能讓子元件把資料傳回插槽,父層再決定怎麼渲染,適合表格列、下拉選項。

拆元件的尺度

一塊 UI 出現第二次、或單檔已經難掃讀,就拆。不要為了「看起來元件化」把每一行按鈕都做成檔案。資料盡量留在真正擁有它的那一層,用 props/emits 傳遞,避免到處 provideinject(那是跨很多層的進階手段)。

跨頁狀態見 Pinia。把邏輯抽出去重用,見 Composables

推薦影音

Vue 組件結構:基本觀念和語法

來源:彭彭的課程

繁中講為什麼要拆元件、父層怎麼引入子元件。同一播放清單接著是 自訂屬性自訂事件,對應本頁 props/emits。