目录
做网站时,你是不是经常遇到这种情况:首页、列表页、详情页都有相同的头部导航和底部版权信息。最笨的办法是每个页面都复制一遍,但改起来就痛苦了------改一个 footer 要改十个文件。Nuxt 的布局系统就是来解决这个问题的。
一、默认布局
布局文件放在 layouts 目录。创建一个默认布局:
mkdir layouts
创建 layouts/default.vue:
<template>
<div class="layout">
<header class="header">
<nav>
<NuxtLink to="/">首页</NuxtLink>
<NuxtLink to="/about">关于</NuxtLink>
<NuxtLink to="/contact">联系</NuxtLink>
</nav>
</header>
<main class="main">
<slot />
</main>
<footer class="footer">
<p>© 2024 我的网站. All rights reserved.</p>
</footer>
</div>
</template>
<style scoped>
.layout {
min-height: 100vh;
display: flex;
flex-direction: column;
}
.header {
background: #fff;
border-bottom: 1px solid #eee;
padding: 1rem;
}
.header nav a {
margin-right: 1rem;
color: #333;
text-decoration: none;
}
.header nav a:hover {
color: #00dc82;
}
.main {
flex: 1;
padding: 2rem;
}
.footer {
background: #f5f5f5;
padding: 1rem;
text-align: center;
color: #666;
}
</style>
然后页面中使用 <NuxtLayout> 包裹内容。但其实 Nuxt 已经自动帮你做了这件事,你只需要写页面内容:
pages/index.vue:
<template>
<div>
<h1>首页</h1>
<p>欢迎来到我的网站</p>
</div>
</template>
页面会自动应用 layouts/default.vue 布局,头部导航和底部版权自动出现。
二、自定义布局
有时候不同页面需要不同的布局。比如管理后台,没有头部导航,而是左侧菜单栏。
创建 layouts/admin.vue:
<template>
<div class="admin-layout">
<aside class="sidebar">
<h3>管理后台</h3>
<nav>
<NuxtLink to="/admin/users">用户管理</NuxtLink>
<NuxtLink to="/admin/articles">文章管理</NuxtLink>
<NuxtLink to="/admin/settings">系统设置</NuxtLink>
</nav>
</aside>
<main class="content">
<slot />
</main>
</div>
</template>
<style scoped>
.admin-layout {
display: flex;
min-height: 100vh;
}
.sidebar {
width: 200px;
background: #2c3e50;
color: white;
padding: 1rem;
}
.sidebar h3 {
margin-bottom: 1rem;
padding-bottom: 1rem;
border-bottom: 1px solid #3c5060;
}
.sidebar nav a {
display: block;
padding: 0.5rem;
color: #b8c7ce;
text-decoration: none;
}
.sidebar nav a:hover {
background: #3c5060;
color: white;
}
.content {
flex: 1;
padding: 2rem;
}
</style>
在页面中指定使用这个布局:
pages/admin/index.vue:
<script setup lang="ts">
definePageMeta({
layout: 'admin' // 指定使用 admin 布局
})
</script>
<template>
<div>
<h1>管理后台首页</h1>
<p>欢迎回来,管理员</p>
</div>
</template>
definePageMeta 是 Nuxt 提供的编译时宏,用于定义页面元信息,包括布局、中间件等。
三、动态切换布局
有时候同一个页面在不同状态下需要不同布局。比如用户登录前后:
<script setup lang="ts">
const { loggedIn } = useUserSession()
// 根据登录状态动态选择布局
definePageMeta({
layout: computed(() => loggedIn.value ? 'default' : 'guest')
})
</script>
或者用 setPageLayout 函数动态切换:
<script setup lang="ts">
const isDark = ref(false)
// 切换布局
const toggleLayout = () => {
isDark.value = !isDark.value
setPageLayout(isDark.value ? 'dark' : 'default')
}
</script>
四、布局嵌套
复杂的系统可能需要布局嵌套。比如一个两栏布局,左侧固定,右侧是内容区,而内容区又需要默认布局的头部和底部。
创建 layouts/two-column.vue:
<template>
<div class="two-column">
<aside class="left-panel">
<slot name="sidebar" />
</aside>
<div class="right-panel">
<slot name="content" />
</div>
</div>
</template>
在 layouts/default.vue 中使用:
<template>
<div class="layout">
<header>...</header>
<main>
<NuxtLayout name="two-column">
<template #sidebar>
侧边栏内容
</template>
<template #content>
<slot /> <!-- 页面内容 -->
</template>
</NuxtLayout>
</main>
<footer>...</footer>
</div>
</template>
五、布局中传递数据
布局和页面之间可以通过 props 传递数据。在布局中定义 props:
<!-- layouts/default.vue -->
<script setup lang="ts">
const props = defineProps<{
title?: string
}>()
</script>
<template>
<div class="layout">
<header>
<h1>{{ title || '我的网站' }}</h1>
</header>
<main>
<slot />
</main>
</div>
</template>
页面中通过 definePageMeta 传递:
<script setup lang="ts">
definePageMeta({
layout: 'default',
layoutProps: {
title: '用户中心'
}
})
</script>
六、命名插槽
布局支持命名插槽,让页面可以往不同区域填充内容:
<!-- layouts/default.vue -->
<template>
<div>
<header>
<slot name="header">
<nav>默认导航</nav>
</slot>
</header>
<main>
<slot />
</main>
<footer>
<slot name="footer">
<p>默认底部</p>
</slot>
</footer>
</div>
</template>
页面中:
<template>
<NuxtLayout>
<template #header>
<nav>自定义导航</nav>
</template>
<div>页面内容</div>
<template #footer>
<p>自定义底部</p>
</template>
</NuxtLayout>
</template>
总结
今天学习了 Nuxt 布局系统:
| 功能 | 实现方式 |
|---|---|
| 默认布局 | layouts/default.vue 自动应用 |
| 自定义布局 | definePageMeta({ layout: 'xxx' }) |
| 动态切换 | setPageLayout() 或 computed |
| 布局嵌套 | 在布局中使用 <NuxtLayout> |
| 传递数据 | layoutProps 配置 |
布局系统让你的页面框架统一管理,改一处全局生效。对于企业级项目来说,这是必不可少的利器。
下一篇文章,我们聊聊页面过渡动画,让页面切换更丝滑。
有帮助就点个赞吧!有问题评论区见 💪