> 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.

# Conditional Rendering

Hiển thị hoặc ẩn phần tử dựa trên điều kiện. Trong AEM, dữ liệu thường đến từ Sling Model qua data attribute, nên điều kiện hay dùng để hiện block khi field có giá trị, ẩn khi rỗng.

## v-if / v-else-if / v-else

`v-if` render phần tử khi điều kiện đúng. Khi sai, phần tử không tồn tại trong DOM.

```html
<div v-if="status === 'active'">Đang hoạt động</div>
<div v-else-if="status === 'pending'">Chờ duyệt</div>
<div v-else>Không xác định</div>
```

Quy tắc: `v-else` và `v-else-if` phải nằm ngay sau phần tử có `v-if` (hoặc `v-else-if`), không được chèn phần tử khác ở giữa.

## v-show

`v-show` luôn render phần tử vào DOM, chỉ bật/tắt bằng CSS `display`.

```html
<div v-show="isVisible">Nội dung</div>
```

Khi `isVisible` sai, DOM vẫn có phần tử nhưng `style="display: none"`.

## v-if vs v-show

| Tiêu chí               | v-if                      | v-show                         |
| ---------------------- | ------------------------- | ------------------------------ |
| Cách hoạt động         | Thêm/xóa phần tử khỏi DOM | Giữ trong DOM, đổi CSS display |
| Chi phí khi toggle     | Cao (mount/unmount lại)   | Thấp (chỉ đổi CSS)             |
| Chi phí render lần đầu | Thấp nếu điều kiện sai    | Luôn render                    |
| Hỗ trợ v-else          | Có                        | Không                          |
| Dùng với template      | Có                        | Không                          |

Quy tắc chọn:

- Toggle thường xuyên (tab, dropdown, accordion): dùng `v-show`.
- Điều kiện ít đổi hoặc block nặng có thể không bao giờ hiện: dùng `v-if`.

## Điều kiện cho nhóm phần tử với template

`v-if` chỉ áp cho một phần tử. Cần điều kiện cho nhiều phần tử mà không thêm thẻ bọc thừa thì dùng `<template>` (không render ra DOM).

```html
<template v-if="hasContent">
  <h2>{{ title }}</h2>
  <p>{{ description }}</p>
</template>
```

`v-show` không dùng được với `<template>`.

## v-if với v-for

Không đặt `v-if` và `v-for` trên cùng một phần tử. Ở Vue 2, `v-for` ưu tiên cao hơn `v-if`, nên `v-if` chạy lại cho từng item, gây khó đọc và tốn hiệu năng.

```html
<!-- SAI: v-if chạy trên từng user -->
<li v-for="user in users" v-if="user.active" :key="user.id">
  {{ user.name }}
</li>
```

Cách đúng: lọc bằng `computed` trước, hoặc bọc `v-if` ra ngoài.

```html
<!-- ĐÚNG: lọc bằng computed -->
<li v-for="user in activeUsers" :key="user.id">
  {{ user.name }}
</li>
```

```js
computed: {
  activeUsers() {
    return this.users.filter(u => u.active)
  }
}
```

Điều kiện áp cho cả danh sách thì bọc ngoài bằng `<template v-if>`:

```html
<template v-if="users.length">
  <li v-for="user in users" :key="user.id">{{ user.name }}</li>
</template>
```

## key để kiểm soát tái sử dụng phần tử

Khi toggle giữa hai nhánh cùng loại phần tử, Vue tái sử dụng DOM cũ để tối ưu, có thể giữ lại state không mong muốn (vd giá trị input). Thêm `key` khác nhau để ép Vue render lại phần tử mới.

```html
<input v-if="mode === 'email'" placeholder="Email" key="email">
<input v-else placeholder="Số điện thoại" key="phone">
```

## Tips cho AEM

HTL đã render fallback HTML server-side. Khi Vue mount lên, dùng điều kiện để hiện block tương ứng dữ liệu từ Sling Model.

```html
<!-- HTL render mount point + data -->
<div id="promo" data-promo="${model.promoJson}"></div>
```

```js
new Vue({
  el: '#promo',
  data() {
    return {
      promo: JSON.parse(this.$el.dataset.promo || '{}')
    }
  }
})
```

```html
<!-- template Vue -->
<div>
  <span v-if="promo.label" class="badge">{{ promo.label }}</span>
  <p v-else>Chưa có khuyến mãi</p>
</div>
```

Ưu tiên `v-if` cho block phụ thuộc field tùy chọn (có thể rỗng) để DOM gọn. Dùng `v-show` cho phần đóng/mở liên tục theo tương tác người dùng.
