Đăng nhập

BÀI 13: DYNAMIC ROUTE & SLUG TRONG NUXTJS

Chúng ta tiếp tục với Bài 13 – Dynamic Route và Slug URL trong NuxtJS. Đây là một phần cực kỳ quan trọng để bạn xây dựng blog, trang chi tiết sản phẩm, hồ sơ người dùng… với đường dẫn thân thiện và dễ SEO.


1. Dynamic Route là gì?

Dynamic Route (route động) cho phép bạn tạo một template chung cho nhiều trang khác nhau, ví dụ:

  • /blog/hello-nuxt
  • /blog/vue-3-la-gi
  • /product/ao-thun-dep

Chỉ cần 1 file duy nhất, Nuxt tự động khớp URL → render nội dung đúng.


2. Tạo dynamic route với [slug].vue

Trong thư mục pages/blog/, tạo file:

pages/
└── blog/
└── [slug].vue

Ví dụ hiển thị bài viết theo slug:

<script setup>
const route = useRoute()

const { data: post } = await useAsyncData(() =>
queryContent('/blog').where({ _path: `/blog/${route.params.slug}` }).findOne()
)

if (!post.value) {
throw createError({ statusCode: 404, statusMessage: 'Không tìm thấy bài viết' })
}
</script>

<template>
<div v-if="post">
<h1>{{ post.title }}</h1>
<ContentRenderer :value="post" />
</div>
</template>

3. Tạo slug thân thiện trong Markdown

Trong content/:

content/
└── blog/
├── hello-nuxt.md
└── vue-co-ban.md

Trong hello-nuxt.md:

---
title: Hello Nuxt
description: Giới thiệu nhanh về NuxtJS
date: 2025-07-07
---

# Hello Nuxt

Bài viết đầu tiên...

→ File tên hello-nuxt.md → tương ứng route /blog/hello-nuxt


4. Lấy slug từ nhiều segment

Nếu bạn muốn cấu trúc như /blog/vue/hello-nuxt, thì dùng:

pages/blog/[...slug].vue

route.params.slug lúc này là array: ['vue', 'hello-nuxt']

Bạn cần nối lại:

const fullPath = '/blog/' + route.params.slug.join('/')

5. Hiển thị 404 nếu không có bài viết

if (!post.value) {
throw createError({ statusCode: 404, statusMessage: 'Không tìm thấy bài viết' })
}

→ Nuxt sẽ tự redirect về trang 404.

Bạn có thể tùy chỉnh giao diện 404 trong error.vue.


6. Preview SEO-friendly URLs

URLBài viếtFile
/blog/vue-co-banVue cơ bảnvue-co-ban.md
/blog/hoc-nuxt-chi-tietHọc NuxtJShoc-nuxt-chi-tiet.md

→ Không cần định nghĩa từng route thủ công như với Vue CLI


7. Optional: Tạo slug riêng trong frontmatter

Nếu muốn chủ động kiểm soát slug, bạn có thể làm:

---
title: Bài viết tùy chọn
slug: gioi-thieu-nuxt
---

→ Khi đó bạn cần đổi truy vấn:

queryContent('/blog').where({ slug: route.params.slug }).findOne()

Bạn đã học được

  • Tạo dynamic route với [slug].vue
  • Đọc dữ liệu tương ứng với slug từ Markdown
  • Xử lý khi không tìm thấy (404)
  • Cấu trúc thư mục content để có slug đẹp
  • Dùng [...slug].vue cho URL lồng nhau

Bài tập mở rộng

  1. Tạo ít nhất 3 bài viết trong content/blog/ với tên tệp slug thân thiện
  2. Dùng [slug].vue hiển thị chi tiết bài viết
  3. Thêm logic 404 nếu bài không tồn tại
  4. Trang /blog hiển thị danh sách bài + link đến chi tiết

Thảo luận

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *

Đăng ký nhận tin mới

Nhận bài học, tài nguyên và cơ hội việc làm qua email hàng tuần.

Chúng tôi cam kết không spam. Bạn có thể hủy bất cứ lúc nào.