Cùng tiếp tục với Bài 18 – Tạo trang Tag động và lọc bài viết theo chủ đề. Đây là bước cần thiết để tổ chức nội dung blog của bạn rõ ràng hơn, giúp người đọc dễ dàng tìm thấy các bài viết theo từng chủ đề cụ thể như “Vue”, “Nuxt”, “JavaScript”, “Performance”…
BÀI 18: TRANG TAG ĐỘNG & LỌC BÀI VIẾT THEO CHỦ ĐỀ
1. Mục tiêu bài học
- Hiển thị danh sách tag
- Tạo route động
/tags/[tag].vue
- Lọc bài viết theo tag tương ứng
- Hiển thị giao diện đẹp, thân thiện SEO
2. Thêm tags vào bài viết Markdown
Trong content/blog/hello-nuxt.md
:
---
title: Hello Nuxt
tags: ['nuxt', 'vue']
date: 2025-07-07
---
3. Tạo route động /tags/[tag].vue
Tạo file: pages/tags/[tag].vue
<script setup>
const route = useRoute()
const tag = route.params.tag
const { data: posts } = await useAsyncData(() =>
queryContent('/blog')
.where({ tags: { $contains: tag } })
.sort({ date: -1 })
.find()
)
</script>
<template>
<section>
<h1>Bài viết với tag: {{ tag }}</h1>
<ul>
<li v-for="post in posts" :key="post._path">
<NuxtLink :to="post._path">{{ post.title }}</NuxtLink>
<small>— {{ post.date }}</small>
</li>
</ul>
<div v-if="!posts.length">
<p>Không tìm thấy bài viết nào với tag này.</p>
</div>
</section>
</template>
4. Hiển thị danh sách tất cả tag
Tạo trang pages/tags/index.vue
:
<script setup>
const { data: allPosts } = await useAsyncData(() =>
queryContent('/blog').find()
)
const tags = computed(() => {
const tagSet = new Set()
for (const post of allPosts.value) {
if (post.tags) {
post.tags.forEach(tag => tagSet.add(tag))
}
}
return Array.from(tagSet)
})
</script>
<template>
<section>
<h1>Tất cả chủ đề</h1>
<ul>
<li v-for="tag in tags" :key="tag">
<NuxtLink :to="`/tags/${tag}`">#{{ tag }}</NuxtLink>
</li>
</ul>
</section>
</template>
5. Gợi ý giao diện UX
- Gắn
badge
màu cho mỗi tag - Sắp xếp tag theo bảng chữ cái hoặc tần suất
- Hiển thị số bài viết trong mỗi tag
→ Nâng cao UX khi blog có nhiều chủ đề
6. Tối ưu SEO cho trang tag
Trong pages/tags/[tag].vue
, thêm SEO:
<script setup>
definePageMeta({
title: `Bài viết về ${tag}`,
meta: [
{ name: 'description', content: `Tổng hợp bài viết liên quan đến ${tag}` },
{ property: 'og:title', content: `Tag: ${tag}` }
]
})
</script>
Bạn đã học được
- Thêm
tags
cho từng bài viết Markdown - Tạo route động
/tags/[tag].vue
- Hiển thị danh sách bài viết theo tag
- Tạo trang
/tags
liệt kê tất cả chủ đề - Áp dụng SEO cho từng tag
Bài tập mở rộng
- Làm component
TagBadge.vue
để tái sử dụng - Hiển thị 5 tag phổ biến nhất trong sidebar
- Tạo route
/categories/[slug].vue
nếu dùng chuyên mục - Gắn
meta
cho từng tag để tối ưu SEO nâng cao
Thảo luận