Skip to content
当前页大纲

布局

pages目录下的页面内容会挂载到<NuxtPage />组件上,并渲染到布局文件的插槽(<slot />)

<NuxtPage />组件相当于Vue-Router<RouterView />

vue
<template>
  <div class="text-red-500">index page</div>
</template>
vue
<template>
  <div>
    app.vue
    <NuxtLayout>
      <NuxtPage />
    </NuxtLayout>
  </div>
</template>
vue
<template>
  <main class="px-4 w-full bg-slate-300">
    <slot />
    [Default Layout]
  </main>
</template>

切换布局的方式

  • 方式一:在页面中使用setPageLayout方法进行切换
vue
<template>
  <div>
    <NuxtLayout>
      <NuxtPage />
    </NuxtLayout>
  </div>
</template>
vue
<script setup lang="ts">
function switchLayout() {
  setPageLayout('home')
}
</script>

<template>
  <div class="text-red-500">
    index page
    <div><button @click="switchLayout">Switch Home Layout</button></div>
  </div>
</template>
  • 方式二:在页面中通过definePageMeta方法切换布局
vue
<template>
  <div>
    <NuxtLayout>
      <NuxtPage />
    </NuxtLayout>
  </div>
</template>
vue
<script setup lang="ts">
definePageMeta({
  layout: 'home'
})
</script>

<template>
  <div>
    <div class="text-red-500">
      index page
    </div>
  </div>
</template>
vue
<template>
  <main class="px-4 w-full bg-green-300">
    <slot />
    <div class="mx-auto mt-5 text-center text-sm opacity-25">[Custom Layout]</div>
  </main>
</template>

布局最佳实践

不要在app.vue中进行布局控制,而是具体到每个页面中进行控制,因为这样可以让每个页面有更好的灵活性

vue
<template>
  <div>
    <NuxtPage />
  </div>
</template>
vue
<template>
  <div>
    <NuxtLayout>
      <template #header>
        <div>header</div>
      </template>
      <div class="text-red-500">index page</div>
      <NuxtLink to="/about"><button>Go about</button></NuxtLink>
      <template #footer>
        <div>footer</div>
      </template>
    </NuxtLayout>
  </div>
</template>
vue
<template>
  <div>
    <NuxtLayout name="home">
      <div>about page</div>
    </NuxtLayout>
  </div>
</template>

切换路由页面不更新

原因是<NuxtLayout>没有用一个普通的 HTML 标签包裹起来,比如<div>

vue
<template>
  <div>
    <NuxtLayout>
      <div>index page</div>
      <NuxtLink to="/about"><button>Go</button></NuxtLink>
    </NuxtLayout>
  </div>
</template>
vue
<template>
  <NuxtLayout>
    <div>index page</div>
    <NuxtLink to="/about"><button>Go</button></NuxtLink>
  </NuxtLayout>
</template>

页面

Nuxt的路由基于Vue-Routerpages目录中的每个Vue文件都会创建一个相应的URL。pages/index.vue文件将被映射到应用程序/路由

动态路由

建立页面文件时,如果命名时将任何内容放在方括号[]内,它将被转换为路由参数。在文件名或目录中混合和匹配多个参数

active
├─ pages/
   └─ users-[group]/
      └─ [id].vue
json
{
  "routes": [
    {
      "name": "users-group-id",
      "path": "/users-:group/:id",
      "component": "pages/users-[group]/[id].vue"
    }
  ]
}

在页面中可以通过useRoute()函数来获取当前路由的参数

vue
<script setup lang="ts">
const route = useRoute()
const { id, group } = route.params
</script>

组件自动引入

默认情况下,Nuxt 会扫描components目录下的所有vue文件

当存在多层次目录结构时,自动引入时所生成的组件类型声明会带上目录名称,例如下面的Button.vue组件,最终得到的类型声明是BaseFooButton,在页面中使用时要这样<BaseFooButton />

├─ components
   └─ base
      └─ foo
         └─ Button.vue

如果不想让类型声明带上目录名称,可以把pathPrefix设置为false

这时候Button.vue组件的类型声明就是Button了,在页面中使用时直接<Button />即可

ts
export default defineNuxtConfig({
  components: [
    {
      path: '~/components',
      pathPrefix: false, 
    },
  ],
})

💥注意

但是这样做的话就难免会出现组件同名的情况,即多个组件共用一个组件类型声明,这并不是一个好事。所以不推荐这样做

MIT License.