Skip to content

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 :class: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

  1. 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).
  2. Tạo component Vue App.vue mới trong dự án vanguard-store của bạn.
  3. Trong script setup, khai báo các biến ref mô tả thông tin sản phẩm đầu tiên:
  4. Trên template của App.vue, copy đoạn HTML của PRODUCT CARD 1 (dòng 122-150 trong index.html).
  5. Thực hiện:
    • Dùng v-bind (:src: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ái isHovered. Nếu isHovered bằng true, hãy thêm class CSS shadow-2xlborder-indigo-300 thông qua class binding động (:class).

❓ 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-modelv-bind là gì?

  • A. v-bind là hai chiều, v-model là một chiều.
  • B. v-bind chỉ dùng cho class, v-model dùng cho style.
  • C. v-bind ràng buộc dữ liệu một chiều (từ script ra template), v-model rà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.html trong bài giảng markdown mà truy cập qua link tải.

Released under the MIT License.