Nuxt3目录结构(一)

2,160 阅读5分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第3天,点击查看活动详情

前言🥠

因为Nuxt是约定大于配置的一个框架,所对应的目录结构的名称基本都是规定的,所以有必要解释一下Nuxt对应的目录结构啦🦺

  • 脚手架生成目录结构👇
├── app.vue # Nuxt 3 应用程序中的主组件 入口组件
├── components # 组件目录,支持自动导入
|  └── helloWorld.vue # 组件
├── nuxt.config.ts # Nuxt 配置文件,可以理解成vue.config.js 文件名必须是nuxt.config 后缀名可以是.js,.ts或.mjs
├── package.json # 项目包的配置文件和项目的启动调式命令配置
├── README.md # 搭建 Nuxt 3脚手架之后的阅读文档
├── tsconfig.json # ts配置
└── yarn.lock # yarn锁文件 锁定依赖包版本

Nuxt是约定式开发 白话就是你要按照Nuxt规定的模式进行开发🍕,约定大于配置,比如组件的自动导入🥩,你无需在定义components进行声明,如果定义A你就要定义A,不要定义成B🌯。

Nuxt 提供了一个可遵循的目录结构,专注于特定功能,让您专注于创建,而不是配置🥗。

  • nuxt约定的目录结构如下👇
├── app.vue # Nuxt 3 应用程序中的主组件 入口组件
├── components # 组件目录,支持自动导入
├── layouts # 布局目录
├── composables # 公共函数,支持自动导入
├── assets # 静态资源目录 与vue项目的assets相同
├── middleware # 路由中间件框架
├── nuxt.config.ts  # Nuxt 配置文件,可以理解成vue.config.js 文件名必须是nuxt.config 后缀名可以是.js,.ts或.mjs
├── package.json
├── pages # 基于文件的路由
├── plugins #插件
├── public # 不会参与打包,与vue项目的public类似直接挂在服务器的根目录
├── README.md
├── server
├── tsconfig.json
└── yarn.lock

目录详解

app.vue

相信用过vue的小伙伴都知道app.vue🧀,在nuxt中的app.vuevue中的功能是相同的,在app.vue中定义的jscss都是全局的并包含在每个页面中🍺。

<!--app.vue-->
<template>
  <div>
    <NuxtWelcome />
  </div>
</template>

components目录

  • 单层组件

components目录中对应的是组件目录在使用组件的过程中是无需引用的。

| components/
--| TheHeader.vue
--| TheFooter.vue
<!-- app.vue -->
<template>
  <div>
    <TheHeader />
    <TheFooter />
  </div>
</template>

nuxt对于组件的大小写是不敏感的即使在使用的时候开头字母小写也是可以的<theHeader />

  • 嵌套组件
| components/
--| base/
----| foo/
------| Button.vue

嵌套组件就是组件不是在components的目录下而是在components的子目录或者孙目录下,在使用的时候需要加上上级目录的文件名。

<!-- app.vue -->
<template>
  <div>
    <BaseFooButton />
  </div>
</template>
  • 特殊的嵌套组件
 | components/
--| test/
----| test.vue

如果组件名和对应的目录名称是相同的就不需要增加文件名前缀了。

<!-- app.vue -->
<template>
  <div>
    <Test />
  </div>
</template>
  • 动态组件

使用vue中动态组件的写法要使用resolveComponent语法

<template>
  <div>
    <component :is="isHeader ? TheHeader : 'div'" />
  </div>
</template>
<script setup>
const isHeader = ref(1)
// 组件
const TheHeader = resolveComponent('TheHeader')
</script>
  • 延迟加载组件

您只需在组件名称中添加Lazy前缀即可,可以想象成路由的懒加载🥠,只有在组件显示的时候才进行加载,会大大减少打包之后的大小,如果某些组件不经常显示就可以采用组件的懒加载🧃。

<template>
  <div>
    <LazyTheHeader v-if="show" />
    <button v-if="!show" @click="show = true">ShowHeader</button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      show: false
    }
  }
}
</script>
  • 显式导入组件

虽然nuxt提供了自动导入组件的功能,但是如果想要显式导入组件也是可以的,采用以下语法

<script setup>
  import { TheHeader } from '#components'
</script>

注意
显式导入的组件的方式由于是解构所有要个按照组件的标准首字母要大写,否则会导入失败。

  • ClientOnly

Nuxt提供了仅在客户端故意渲染组件的组件。要仅在客户端上导入组件,请在仅客户端插件中注册该组件,插槽作为后备

  <template>
  <div>
    <ClientOnly>
      <TheHeader />
      <template #fallback>
        <p>Loading comments...</p>
      </template>
    </ClientOnly>
  </div>
</template>

以上代码会先显示Loading comments...当客户端将组件导入成功之后才会展示TheHeader的内容🍘, 当在f12查看网页源代码的时候是看不到TheHeader中定义的内容的,因为客户端渲染把内容都打包进js当中了🥡。

composables目录

该目录与components目录类似,🍠但是这个目录下存放的一般是公共方法不是公共组件,当我们在开发vue程序的时候的utils目录,该目录也可以实现自动导入的功能,但是也有特殊情况👇。

composables
 | - utils.ts // 可以自动导入
 | - utilsfun
 | --- funtest.ts // 不可以自动导入
 | --- index.ts // 可以自动导入

如果导出函数的时候使用export default 则需要通过文件名的方式进行调用

// utils.ts 文件
export const getTime=()=>{
    return new Date();  
}
export default function test(){
  console.log('默认导出')
}
  <!-- app.vue -->
  <template>
  <div>
  </div>
</template>
<script setup>
// 成功
console.log(getTime())
// 成功 如果想使用test必须显示导入utils文件或者使用utils()进行调用,因为test是默认导出的
utils()
// 报错
test()
</script>

pages目录

基于文件的路由,如果不创建该文件夹nuxt不会引用vue-router如果创建了pages文件夹nuxt将自动引入vue-router来管理路由。

  • 对应关系

pages/index.vue 会自动映射/,如果是pages/test.vue会自动映射到/test

重点
必须要保证app.vue中有<NuxtPage />标签来展示路由下的内容,可以理解成vue中的router-view

  • 动态路由
    可以直接通过文件名的方式进行传递参数,要保证路由跳转时与文件名的结构一致。

    • 单参数传递✨: 只要在页面的文件名中用[]扩起来就可以了。
    • 多参数传递✨: 需要建立一个父级文件夹进行接收也使用[]进行包裹。
  • 参数接收
    参数接收的方式与vue接收的方式一致。

  • 捕获所有路由
    可以通过[...xxx].vue的方式定义路由,可以无限层级跳转。

  • 嵌套路由
    类似vue-router中的children,并且需要在父级中增加<NuxtPage />将其理解成vue-router中的嵌套路由就很好理解,当跳转到子路由中将含有父级中的内容🚝。

  • 路由跳转

    • 标签导航🍺:路由跳转需要使用<NuxtLink to="/">Home page</NuxtLink>进行跳转
    • 编程式导航🍺: navigateTo()
  • 举个例子最全👇


pages
├── demo2_[id].vue
├── [...catch].vue
├── goods-[name]
|  └── demo3-[id].vue
├── parent
   └── child.vue
├── parent.vue
├── index.vue
  <!-- pages/index.vue -->
  <template>
  <div class=""><h1 @click="routerPush">Index Page</h1></div>
  <NuxtLink to="/parent/child">/parent/child</NuxtLink>
  <NuxtLink to="/catch/xxx/aaa/vvvv">catch.vue</NuxtLink>
  <NuxtLink to="/demo2_38">Demo2.vue</NuxtLink>
  <NuxtLink to="/goods-haha/demo3-test">Demo3.vue</NuxtLink>
</template>
<script setup>
import {} from "vue";
const routerPush= ()=>{
  navigateTo({
    path:'/goods-bar/demo3-foo',
    query:{
      queryPms:123
    }
  })
}
</script>

<style scoped></style>
  <!--app.vue-->
<template>
  <div>
    <NuxtPage></NuxtPage>
  </div>
</template>
<script setup>
</script>
  <!--demo3-[id].vue-->
<template>
    <div class="">获取的id:{{ $route.params.id }}</div>
  <div class="">获取的query参数:{{ $route.query.queryPms }}</div>
</template>
<script setup>
import { } from "vue";
import { ref } from "vue";
const route = useRoute();
const id = ref(route.params.id);
const name = ref(route.params.name)
</script>

<style scoped>
</style>
  <!-- parent.vue -->
<template>
  <div class="">Parent Page</div>
  <!-- 子页面的出口-->
  <NuxtChild></NuxtChild>
</template>

<script setup>
import {} from "vue";
</script>

<style scoped></style>
    <!-- child.vue -->
<template>
  <div class="">Child Page</div>
</template>

<script setup>
import {} from "vue";
</script>

<style scoped></style>

总结

Nuxt3的目录结构非常重要且比较多,一节很难消化,所以打算分成两节,一起加油吧🚗

参考链接