For AI agents: the complete documentation index is available at https://nhanbe.id.vn/llms.txt, the full documentation bundle is available at https://nhanbe.id.vn/llms-full.txt, and this page is available as Markdown at https://nhanbe.id.vn/frontend/vue2.7/component-in-depth/slots.md.

Using default, named, and scoped slots for component composition in Vue 2.7.

Slots

Slot cho phép cha truyền nội dung (template) vào trong con. Props truyền dữ liệu, slot truyền markup. Dùng để tạo component bao bọc (layout, card, modal) mà nội dung bên trong do nơi sử dụng quyết định.

Slot cơ bản

Con đặt <slot> làm chỗ chứa. Nội dung cha đặt giữa thẻ component sẽ thay vào đó.

<!-- Child: AlertBox.vue -->
<template>
  <div class="alert">
    <slot></slot>
  </div>
</template>
<!-- Parent -->
<alert-box>
  Có lỗi xảy ra.
</alert-box>

Fallback content

Nội dung mặc định bên trong <slot> hiển thị khi cha không truyền gì.

<template>
  <button class="btn">
    <slot>Submit</slot>
  </button>
</template>

<submit-button></submit-button> hiện "Submit". Truyền nội dung thì ghi đè fallback.

Named slots

Nhiều vùng nội dung thì đặt tên slot bằng attribute name. Cha nhắm slot bằng v-slot:name trên <template>.

<!-- Child: BaseLayout.vue -->
<template>
  <div class="layout">
    <header><slot name="header"></slot></header>
    <main><slot></slot></main>
    <footer><slot name="footer"></slot></footer>
  </div>
</template>
<base-layout>
  <template v-slot:header>
    <h1>Tiêu đề</h1>
  </template>

  <p>Nội dung chính vào default slot.</p>

  <template v-slot:footer>
    <p>Chân trang</p>
  </template>
</base-layout>

Slot không tên là default slot. v-slot:header rút gọn thành #header.

Scoped slots

Khi nội dung slot cần dữ liệu từ chính con, con bind dữ liệu lên <slot> (slot props), cha nhận qua v-slot.

<!-- Child: UserList.vue -->
<template>
  <ul>
    <li v-for="user in users" :key="user.id">
      <slot :user="user"></slot>
    </li>
  </ul>
</template>

<script>
export default {
  props: { users: Array }
}
</script>
<!-- Parent quyết định cách render mỗi user -->
<user-list :users="users">
  <template v-slot:default="{ user }">
    <strong>{{ user.name }}</strong> - {{ user.email }}
  </template>
</user-list>

Scoped slot tách logic (con cung cấp dữ liệu) khỏi trình bày (cha quyết định markup). Dùng cho list, table tái sử dụng.

Tóm tắt

Loại slotMục đích
Default slotMột vùng nội dung duy nhất
Named slotNhiều vùng nội dung có tên
Scoped slotCha render nhưng cần dữ liệu từ con

Tips cho AEM

Slot hữu ích cho layout/wrapper component dùng lại nhiều nơi trong frontend. Lưu ý: slot là khái niệm phía Vue, không liên quan HTL. HTL chèn nội dung server-side bằng data-sly-resource hoặc data-sly-include, còn slot chỉ hoạt động bên trong cây Vue đã mount.

<!-- CardPanel.vue tái sử dụng -->
<template>
  <section class="card">
    <h3 class="card__title">
      <slot name="title">Mặc định</slot>
    </h3>
    <div class="card__body">
      <slot></slot>
    </div>
  </section>
</template>