Buổi 2: Template Syntax & Directives
🎯 Mục tiêu học tập
- Sử dụng thành thạo cú pháp nội suy văn bản Mustache (
) và thẻv-html. - Áp dụng directive
v-bindđể liên kết thuộc tính động (Attributes binding) gồm cả Class & Style binding. - Sử dụng
v-modelđể thực hiện liên kết dữ liệu hai chiều (Two-way data binding) trên các form nhập liệu. - Sử dụng
v-on(hoặc@) để bắt các sự kiện và xử lý.
📖 Lý thuyết cốt lõi
1. Interpolation (Nội suy)
- Text: Sử dụng cặp dấu ngoặc nhọn kép
. - Raw HTML: Mặc định Vue chuyển đổi HTML thành text để chống tấn công XSS. Để hiển thị HTML thực tế, dùng
v-html.vue<p v-html="rawHtmlContent"></p>
2. Attribute Binding (v-bind hoặc :)
Dùng để ràng buộc một thuộc tính HTML với một biến trong script.
vue
<!-- Đầy đủ -->
<a v-bind:href="url">Link</a>
<!-- Rút gọn -->
<a :href="url">Link</a>- Class & Style binding: Có thể truyền đối tượng hoặc mảng vào
:classvà:style.vue<div :class="{ active: isActive, 'text-danger': hasError }"></div>
3. Two-way Data Binding (v-model)
- Ràng buộc hai chiều giữa State và phần tử nhập liệu của Form (input, select). Khi người dùng nhập, state tự cập nhật, và ngược lại.vue
<input v-model="email" placeholder="Nhập email" />
4. Event Handling (v-on hoặc @)
Lắng nghe các sự kiện DOM và kích hoạt hàm xử lý.
vue
<button @click="sayHello">Click Me</button>- Event Modifiers:
stop(stopPropagation),prevent(preventDefault).vue<form @submit.prevent="onSubmit">...</form>
💻 Ví dụ thực tiễn
vue
<script setup>
import { ref } from 'vue'
const email = ref('')
const isAgreed = ref(false)
const themeColor = ref('blue')
const activeClass = ref('bold-text')
function handleSubmit() {
alert(`Đăng ký thành công email: ${email.value}`);
}
</script>
<template>
<div class="form-container">
<h2>Đăng Ký Nhận Bản Tin</h2>
<!-- Bind class và style động -->
<p :style="{ color: themeColor }" :class="activeClass">
Điền thông tin của bạn bên dưới:
</p>
<!-- Two-way Binding với v-model -->
<div class="field">
<label>Email: </label>
<input type="email" v-model="email" placeholder="example@gmail.com" />
</div>
<div class="field">
<label>
<input type="checkbox" v-model="isAgreed" /> Tôi đồng ý với điều khoản
</label>
</div>
<!-- Event Handling với v-on và modifier prevent -->
<form @submit.prevent="handleSubmit">
<button type="submit" :disabled="!isAgreed">Gửi Đăng Ký</button>
</form>
</div>
</template>
<style scoped>
.form-container {
max-width: 400px;
margin: 20px auto;
padding: 15px;
border: 1px solid #ccc;
border-radius: 6px;
}
.field {
margin-bottom: 15px;
}
.bold-text {
font-weight: bold;
}
button {
padding: 8px 16px;
cursor: pointer;
}
button:disabled {
background-color: #ddd;
cursor: not-allowed;
}
</style>🛠️ Bài tập thực hành (Lab)
Yêu cầu: Đổ dữ liệu động và xử lý tương tác trên Giao diện trang chủ Vanguard Store
- Hãy mở tệp HTML trang chủ index.html (đặc biệt chú ý vùng sản phẩm từ dòng 122 đến 150).
- Tạo component Vue
App.vuemới trong dự ánvanguard-storecủa bạn. - Trong script setup, khai báo các biến ref mô tả thông tin sản phẩm đầu tiên:
productName(ref string, ví dụ: "Tai Nghe Vanguard Studio Wireless")productPrice(ref number, ví dụ: 3500000)productCategory(ref string, ví dụ: "Âm thanh")productImage(ref string, ví dụ: "https://images.unsplash.com/photo-1505740420928-5e560c06d30e?w=500&auto=format&fit=crop&q=60")isHovered(ref boolean, mặc định false)
- Trên template của
App.vue, copy đoạn HTML của PRODUCT CARD 1 (dòng 122-150 trong index.html). - Thực hiện:
- Dùng
v-bind(:srcvà:alt) để binding ảnh sản phẩm từproductImage. - Dùng interpolation
để hiển thị tên sản phẩm, danh mục, và giá bán. - Sử dụng sự kiện mouseover và mouseleave (
@mouseover,@mouseleave) để cập nhật trạng tháiisHovered. NếuisHoveredbằng true, hãy thêm class CSSshadow-2xlvàborder-indigo-300thông qua class binding động (:class).
- Dùng
❓ Trắc nghiệm nhanh
1. Đâu là cú pháp rút gọn của directive v-bind:class?
- A.
@class - B.
#class - C.
:class - D.
&classĐáp án đúng: C.
2. Modifier nào được dùng để ngăn chặn hành động tải lại trang mặc định của Form?
- A.
.stop - B.
.prevent - C.
.capture - D.
.selfĐáp án đúng: B.
3. Sự khác biệt giữa v-model và v-bind là gì?
- A.
v-bindlà hai chiều,v-modellà một chiều. - B.
v-bindchỉ dùng cho class,v-modeldùng cho style. - C.
v-bindràng buộc dữ liệu một chiều (từ script ra template),v-modelràng buộc hai chiều. - D. Không có sự khác biệt. Đáp án đúng: C.
4. Khi bind đường dẫn ảnh sản phẩm :src="productImage", chúng ta đang sử dụng directive nào?
- A.
v-on - B.
v-model - C.
v-bind - D.
v-textĐáp án đúng: C.
5. Lắng nghe sự kiện di chuột rời khỏi thẻ dùng sự kiện nào?
- A.
@click - B.
@mouseover - C.
@mouseleave - D.
@keydownĐáp án đúng: C.
📝 Checklist hoàn thành
- [ ] Ràng buộc thành công thuộc tính ảnh
:srcđộng. - [ ] Bind class thành công dựa trên trạng thái hover của card sản phẩm.
- [ ] Không hiển thị toàn bộ code HTML thô của
index.htmltrong bài giảng markdown mà truy cập qua link tải.