Khám phá chức năng ẩn của thẻ template trong Vue 3

Trong Vue.js, thẻ <template> đóng vai trò như một container logic, giúp nhóm các phần tử mà không tạo ra node thừa trên DOM thực tế. Điều này đặc biệt hữu ích khi làm việc với các chỉ thị điều kiện, vòng lặp hoặc cơ chế truyền nội dung qua slots.

Khởi tạo Component trong SFC

Trong các file đơn thành phần (Single File Components), thẻ này bao bọc toàn bộ cấu trúc giao diện. Dưới đây là cách tổ chức mã nguồn sử dụng Composition API:

<template>
  <div class="widget">
    <h2>{{ pageTitle }}</h2>
    <p>{{ description }}</p>
  </div>
</template>

<script setup>
import { ref } from 'vue';

const pageTitle = ref('Trạng thái hệ thống');
const description = ref('Đang hoạt động bình thường');
</script>

Điều khiển luồng hiển thị

Khi cần áp dụng v-if hoặc v-for cho nhiều phần tử cùng lúc mà không muốn thêm thẻ <div> wrapper, <template> là giải pháp tối ưu.

Sử dụng v-if

<template>
  <div class="dashboard">
    <template v-if="isAuthorized">
      <button @click="handleExit">Thoát</button>
      <span>Xin chào, quản trị viên</span>
    </template>
    <template v-else>
      <button @click="handleEnter">Đăng nhập</button>
      <span>Khách truy cập</span>
    </template>
  </div>
</template>

<script setup>
import { ref } from 'vue';

const isAuthorized = ref(false);

const handleEnter = () => isAuthorized.value = true;
const handleExit = () => isAuthorized.value = false;
</script>

Sử dụng v-for

<template>
  <div class="list-container">
    <template v-for="task in taskList" :key="task.id">
      <dt>{{ task.title }}</dt>
      <dd>{{ task.status }}</dd>
    </template>
  </div>
</template>

<script setup>
import { reactive } from 'vue';

const taskList = reactive([
  { id: 101, title: 'Kiểm tra mã', status: 'Hoàn thành' },
  { id: 102, title: 'Triển khai', status: 'Đang chờ' }
]);
</script>

Tương tác với Slots

Thẻ <template> còn là chìa khóa để định nghĩa nội dung truyền vào slots, đặc biệt là slots có tên và scoped slots.

Named Slots

Component con (LayoutWrapper.vue):

<template>
  <div class="layout">
    <nav><slot name="navigation"></slot></nav>
    <section><slot></slot></section>
  </div>
</template>

Component cha sử dụng:

<template>
  <LayoutWrapper>
    <template #navigation>
      <a href="/home">Trang chủ</a>
    </template>
    <p>Nội dung chính của trang</p>
  </LayoutWrapper>
</template>

<script setup>
import LayoutWrapper from './LayoutWrapper.vue';
</script>

Scoped Slots

Cho phép component con truyền dữ liệu ngược lại cho slot của component cha.

Component con (DataProvider.vue):

<template>
  <div>
    <slot :user-info="userData"></slot>
  </div>
</template>

<script setup>
import { ref } from 'vue';

const userData = ref({ name: 'Nguyen Van A', role: 'Dev' });
</script>

Component cha nhận dữ liệu:

<template>
  <DataProvider v-slot="{ userInfo }">
    <div class="profile">
      <h3>{{ userInfo.name }}</h3>
      <p>Chức vụ: {{ userInfo.role }}</p>
    </div>
  </DataProvider>
</template>

<script setup>
import DataProvider from './DataProvider.vue';
</script>

Dữ liệu lúc này đã được sử dụng trực tiếp trong template cha để hiển thị thông tin động.

Thẻ: vuejs Vue3 composition-api component-slots single-file-components

Đăng vào ngày 25 tháng 6 lúc 08:25