Tiếp theo là Bài 11 – Layout động nâng cao cho blog & định nghĩa layout theo loại trang. Đây là bước mở rộng giúp bạn xây dựng các giao diện riêng biệt cho từng phần của website như: blog, admin, landing page…
1. Mục tiêu bài học
- Tách layout riêng cho blog (header khác, không sidebar, v.v.)
- Sử dụng
definePageMeta({ layout: '...' })
để gán layout - Tạo layout riêng cho phần quản trị (admin)
2. Tạo layout layouts/blog.vue
<template>
<div class="blog-layout">
<header>
<h1>Blog Cá Nhân</h1>
<nav>
<NuxtLink to="/">Trang chủ</NuxtLink> |
<NuxtLink to="/blog">Blog</NuxtLink>
</nav>
</header>
<main>
<slot />
</main>
<footer>
<p>© 2025 – Blog Vue của bạn</p>
</footer>
</div>
</template>
<style scoped>
header {
background-color: #f9f9f9;
padding: 16px;
}
nav a {
margin-right: 10px;
}
main {
padding: 24px;
max-width: 760px;
margin: auto;
}
</style>
3. Áp dụng layout cho trang blog
Ví dụ trong pages/blog/index.vue
<script setup>
definePageMeta({
layout: 'blog'
})
const { data: articles } = await useAsyncData(() =>
queryContent().sort({ date: -1 }).find()
)
</script>
Tương tự trong pages/blog/[...slug].vue
:
<script setup>
definePageMeta({
layout: 'blog'
})
const { params } = useRoute()
const { data: post } = await useAsyncData(() =>
queryContent().where({ _path: `/blog/${params.slug}` }).findOne()
)
</script>
→ Cả danh sách và chi tiết bài viết đều dùng layout blog.vue
4. Tạo layout riêng cho Admin (tuỳ chọn)
Tạo file: layouts/admin.vue
<template>
<div class="admin-layout">
<aside>
<NuxtLink to="/admin">Dashboard</NuxtLink><br />
<NuxtLink to="/admin/posts">Bài viết</NuxtLink>
</aside>
<main>
<slot />
</main>
</div>
</template>
<style scoped>
.admin-layout {
display: flex;
}
aside {
width: 200px;
background: #eee;
padding: 10px;
}
main {
padding: 20px;
flex: 1;
}
</style>
Sau đó trong các file pages/admin/*.vue
, bạn dùng:
<script setup>
definePageMeta({
layout: 'admin'
})
</script>
5. Gán layout tự động theo đường dẫn (nâng cao)
Bạn có thể dùng middleware hoặc plugin để tự động gán layout theo path, nhưng cách rõ ràng nhất vẫn là dùng definePageMeta()
trong mỗi page.
Bạn đã học được
- Tạo layout riêng cho từng khu vực (blog, admin…)
- Sử dụng
definePageMeta({ layout: '...' })
để gán layout - Tổ chức layout phù hợp với từng loại nội dung
- Tối ưu trải nghiệm người dùng với giao diện nhất quán
Bài tập mở rộng
- Tạo layout
landing.vue
cho trang giới thiệu - Trang
/about.vue
dùng layoutlanding
- Trang
/admin/posts.vue
dùng layoutadmin
Thảo luận