Buổi 5: Component & Props (Truyền dữ liệu cha -> con)
🎯 Mục tiêu học tập
- Giải thích được tư duy Component-based trong phát triển giao diện web hiện đại.
- Tạo và import thành công các component con vào component cha.
- Sử dụng thuộc tính
propsđể truyền dữ liệu từ component cha xuống component con. - Định nghĩa kiểu dữ liệu và thực hiện validation cho
props(type, required, default value).
📖 Lý thuyết cốt lõi
1. Kiến trúc Component-based
- Một ứng dụng Vue là một cây gồm các component lồng nhau.
- Mỗi component đại diện cho một phần giao diện độc lập, khép kín (self-contained) bao gồm cả giao diện, logic xử lý và phong cách thiết kế riêng biệt.
2. Khai báo Props trong Vue 3 Composition API
- Dữ liệu trong Vue di chuyển theo cơ chế một chiều từ cha xuống con. Component con không được phép trực tiếp sửa đổi
propsnhận được từ cha. - Để nhận dữ liệu từ cha, con khai báo bằng cách sử dụng compiler macro
defineProps().
vue
<!-- Component con: UserProfile.vue -->
<script setup>
const props = defineProps({
username: {
type: String,
required: true
},
age: {
type: Number,
default: 18
}
})
</script>
<template>
<div class="profile-card">
<h3>Tên: {{ username }}</h3>
<p>Tuổi: {{ age }}</p>
</div>
</template>💻 Ví dụ thực tiễn
vue
<!-- Component cha: App.vue -->
<script setup>
import { ref } from 'vue'
import UserProfile from './components/UserProfile.vue'
const currentAge = ref(25)
</script>
<template>
<!-- Truyền giá trị động (Dynamic Props) dùng v-bind hoặc dấu hai chấm -->
<UserProfile :username="'Trần Thị B'" :age="currentAge" />
</template>🛠️ Bài tập thực hành (Lab)
Yêu cầu: Tách component ProductCard.vue từ template trang chủ Vanguard Store
- Hãy mở tệp HTML trang chủ index.html và copy phần giao diện của PRODUCT CARD 1 (nằm ở dòng 122 đến 150).
- Tạo component Vue con mới tên là
ProductCard.vuetại thư mục/src/components/. - Trong
ProductCard.vue, sử dụngdefineProps()để khai báo các thuộc tính cần nhận:product: Object chứaid,name,price,category,image. Định rõ kiểu dữ liệuObjectvà thuộc tínhrequired: true.
- Thay thế các thông tin tĩnh trong mã HTML vừa copy bằng dữ liệu từ prop
product(sử dụng:src,:altvà). - Tại component cha
App.vue, import componentProductCard.vue. - Sử dụng
v-forlặp qua mảng sản phẩm hiện có và truyền từng object sản phẩm vào prop:productcủa componentProductCardtương ứng:vue<ProductCard v-for="prod in products" :key="prod.id" :product="prod" />
❓ Trắc nghiệm nhanh
1. Tại sao luồng dữ liệu của Props là một chiều (One-way data flow)?
- A. Để tăng dung lượng bộ nhớ đệm của trình duyệt.
- B. Để ngăn các component con vô tình thay đổi trạng thái của component cha, gây khó khăn cho việc gỡ lỗi (debug).
- C. Do Vue không hỗ trợ binding hai chiều.
- D. Do cú pháp template bắt buộc như vậy. Đáp án đúng: B.
2. Đoạn mã HTML cần tách thành component ProductCard nằm ở khoảng dòng nào trong index.html?
- A. Dòng 35 đến 64.
- B. Dòng 122 đến 150.
- C. Dòng 73 đến 99.
- D. Dòng 253 đến 292. Đáp án đúng: B.
3. Để nhận dữ liệu từ cha truyền xuống, component con sử dụng hàm compiler macro nào?
- A.
getProps() - B.
receiveProps() - C.
defineProps() - D.
props()Đáp án đúng: C.
📝 Checklist hoàn thành
- [ ] Tách thành công card sản phẩm thành component con
ProductCard.vueđộc lập. - [ ] Khai báo và validate prop
productkiểu dữ liệu Object trong component con. - [ ] Không hiển thị toàn bộ code HTML thô của
index.htmltrong bài giảng markdown mà sử dụng link.