Skip to content

Vue 作用域插槽 (Scoped Slots) 詳解:打破作用域限制的元件橋樑

在 Vue 的元件體系中,預設遵循著嚴格的單向資料流與作用域限制:父元件無法直接存取子元件內部的資料。

然而,當您開發高度封裝的元件(如:資料表格 DataTable、自動完成列表 Autocomplete)時,「由子元件提供資料,但由父元件決定渲染樣式」 的需求便會出現。這正是 作用域插槽 (Scoped Slots) 大顯身手的時刻。

為什麼需要作用域插槽?

一句話總結:子元件掌握 資料(Data),但不知道如何渲染;父元件掌握 渲染邏輯(UI),但拿不到資料。 作用域插槽就像一座橋樑,讓子元件能像「傳遞 Props」一樣,把內部數據回傳給父元件的插槽內容。

實作步驟:從資料綁定到接收

子元件:定義插槽並「綁定」數據

在子元件中,我們透過 :propName="value" 的方式,將資料掛載到 <slot> 標籤上。

vue
<!-- /components/UserList.vue -->
<script setup>
import { reactive } from "vue";

const users = reactive([
  { id: 9, name: "Away", role: "admin" },
  { id: 10, name: "Tony", role: "user" },
  { id: 11, name: "Mary", role: "user" },
]);
</script>

<template>
  <ul>
    <li v-for="u in users" :key="u.id">
      <slot :user="u"></slot>
    </li>
  </ul>
</template>

父元件:接收數據並「自定義」外觀

父元件透過 v-slot 指令接收一個物件(通常命名為 slotProps),該物件包含了子元件回傳的所有數據。

vue
<!-- /views/Slot.vue -->
<script setup>
import UserList from "@/components/UserList.vue";

function clickHandler(id) {
  console.log(id);
}
</script>

<template>
  <UserList v-slot="slotProps">
    {{ slotProps.user.name }} ({{ slotProps.user.role }})
    <input
      type="button"
      value="edit"
      @click="clickHandler(slotProps.user.id)"
    />
  </UserList>
</template>

TIP

簡單來說,子元件裡有資料,但不知道怎麼渲染;父元件知道怎麼渲染,但沒有資料。作用域插槽就是那座橋樑,讓子元件把資料傳給父元件的插槽內容。

進階技巧:解構插槽 Prop (Destructuring)

為了讓程式碼更簡潔,您可以使用 ES6 解構語法直接取得資料,這是現代 Vue 開發中最推薦的寫法:

vue
<UserList v-slot="{ user }">
  {{ user.name }}
</UserList>