Nuxt3 布局layouts和NuxtLayout的使用详解

作者:键盘侠

时间:2026-10-26

浏览:396

本文详解Nuxt3中layouts目录与NuxtLayout组件的配合使用。通过app.vue全局包裹NuxtLayout实现状态共享,结合definePageMeta配置页面布局与参数,利用computed获取route.meta确保动态内容切换时数据实时更新,解决页面切换参数不同步问题。

文章目录

Nuxt3布局基础与目录结构

Nuxt3是构建在Vue3之上的开发框架,采用服务器端渲染(SSR)技术,能够更便捷地实现Vue应用的SEO优化。

采用Nuxt3的SSR模式开发的网站,其渲染与运行速度极快,性能表现优异,同时具备良好的SEO友好性。

本文将重点介绍Nuxt3中layouts布局目录的具体用法,以及如何配合NuxtLayout组件进行开发。

Nuxt3布局基础与目录结构

首先查看示例项目的目录结构:

Nuxt3布局基础与目录结构

layouts目录与NuxtLayout组件配置

layouts目录通常用于存放页面的公共组件,例如通用的头部导航菜单、底部Footer或侧边栏等。布局本质上是包裹多个页面的公共用户界面容器,如页眉和页脚展示区域。布局通过Vue文件中的<slot />组件来渲染页面内容,默认情况下使用layouts/default.vue文件。自定义布局可以配置为页面元数据的一部分。

以普通页面为例进行说明:

Nuxt3布局基础与目录结构

图中红色圈出的部分为公共区域,我们将其提取至layouts目录中,并在pages目录下的首页(index.vue)和关于页面(about.vue)中进行引入。

其中的NuxtLayout标签用于实现公共布局的自定义与引入功能。

入口文件与全局布局实例

首先查看入口文件app.vue中的写法:

<template>
  <NuxtLayout>
    <NuxtPage />
  </NuxtLayout>
</template>
<script setup>
onMounted(() => {
});
</script>

在入口文件app.vue中使用NuxtLayout进行包裹,可以使整个项目的页面共用一个NuxtLayout实例,从而实现状态、数据及NuxtLayout实例的共享。如果不同页面各自使用NuxtLayout包裹,则会生成多个独立的NuxtLayout实例,导致数据无法共享,甚至可能引发显示错误。

公用布局文件与动态内容替换

接下来查看layouts目录下的公用布局文件:custom.vue

<template>
  <div class="header_container">
    <el-header>
      <el-menu :default-active="activeIndex" class="el-menu-demo" mode="horizontal" :ellipsis="false"
        background-color="#c6e2ff" @select="handleSelect">
        <el-menu-item index="0">LOGO</el-menu-item>
        <el-menu-item index="1">Processing Center</el-menu-item>
        <div class="flex-grow" />
        <el-menu-item index="2">Processing Center</el-menu-item>
        <el-sub-menu index="3">
          <template #title>Workspace</template>
          <el-menu-item index="3-1">item one</el-menu-item>
          <el-menu-item index="3-2">item two</el-menu-item>
          <el-menu-item index="3-3">item three</el-menu-item>
          <el-sub-menu index="3-4">
            <template #title>item four</template>
            <el-menu-item index="3-4-1">item one</el-menu-item>
            <el-menu-item index="3-4-2">item two</el-menu-item>
            <el-menu-item index="3-4-3">item three</el-menu-item>
          </el-sub-menu>
        </el-sub-menu>
      </el-menu>
    </el-header>
  </div>
  <slot />
  <el-footer>Footer 2</el-footer>
</template>
<script setup lang="ts">
const handleSelect = (key: string, keyPath: string[]) => {
};
const route = useRoute();
// const activeIndex = ref("1");
const activeIndex = computed(() => {
  return route.meta.index + ''
})
onMounted(() => {
});
</script>
<style>
.flex-grow {
  flex-grow: 1;
}
.header_container {
  width: 100%;
  margin: 0 auto;
  margin-bottom: 20px;
  background-color: #c6e2ff;
}
.el-header {
  width: 1024px;
  margin: 0 auto;
}
</style>

该页面主要定义了通用的header布局和footer布局。中间动态替换的部分使用了<slot />。即在引入custom.vue公用布局的页面中,包裹的内容会自动替换<slot />部分。

接收从引入布局页面传递过来的动态参数,这里使用了route.meta。需要注意的是,此处采用computed计算属性来存储和获取传递的参数。如果不使用计算属性,测试会发现页面切换时参数无法及时获取,只有手动刷新页面才能获取到传递的参数,因此必须使用computed计算属性来存储和获取传递过来的参数。

... ...
const route = useRoute();
// const activeIndex = ref("1");
const activeIndex = computed(() => {
  return route.meta.index + ''
})
... ...

页面参数传递与computed应用

接着查看首页index.vue是如何引入公用布局custom.vue,以及如何传递参数的。

<template>
  <div class="common-layout">
    <el-container class="mainContainer">
      <el-main>
        <span>我是首页</span>
        <div class="btn_container">
          <el-button type="primary" @click="toAbout()">Primary</el-button>
        </div>
      </el-main>
    </el-container>
  </div>
</template>
<script setup lang="ts">
const router = useRouter();
//这里的layout定义了NuxtLayout引入加载的公共布局文件
//index为我们要通过route.meta传递给公共布局文件的参数
definePageMeta({
  layout: 'custom',
  index: 1,
});
onMounted(() => {
});
function toAbout() {
  router.push("/about");
}
</script>
<style scoped>
.mainContainer {
  width: 1224px;
  margin: 0 auto;
}
.btn_container {
  padding: 20px;
}
</style>

页面template中编写的内容都将挂载并替换到custom.vue中的<slot/>里,从而形成外层顶部和底部固定为custom.vue中的公用布局内容,中间部分为index.vue首页内容的结构。

... ...
definePageMeta({
  layout: 'custom',
  index: 1,
});
... ...

我们通过definePageMeta来指定NuxtLayout使用的布局文件。需要传递给公共布局文件的参数也可以在此处定义。

最后查看关于页面about.vue的写法,整体与index.vue类似。

<template>
    <div class="common-layout">
        <el-container class="mainContainer">
            <el-main>我是关于页面</el-main>
        </el-container>
    </div>
</template>
<script setup lang="ts">
useHead({
    title: '关于页面',
    meta: [
        { name: 'description', content: 'My amazing site.' }
    ],
    bodyAttrs: {
        class: 'test'
    },
    script: [{ children: 'console.log(\'Hello world\')' }]
})
definePageMeta({
  layout:'custom',
  index: 2,
});
onMounted(() => {
});
</script>
<style scoped>
.mainContainer {
    display: block;
    width: 1224px;
    margin: 0 auto;
}
</style>

点击index.vue中的按钮跳转到about.vue页面,about.vue页面效果如下图所示:

Nuxt3布局基础与目录结构

只有中间部分是动态更换的,顶部和底部均为公用的custom.vue布局。

同时注意,首页和关于页面顶部公用菜单导航的选中项是变化的,这是由于传递过来的参数index生效所致。

到此这篇关于Nuxt3 布局layouts和NuxtLayout的使用的文章就介绍到这了,更多相关Nuxt3 布局layouts和NuxtLayout内容请搜索本站以前的文章或继续浏览下面的相关文章希望大家以后多多支持本站!

实用工具推荐

电子包浆

绿化、压缩、噪点和虚拟水印,自由调节做旧程度。

使用 ›
图片压缩

选择画质和输出格式,预览压缩前后的大小。

使用 ›
相关文章