components 自定义全局组件

无需 import

在 Nuxt3 中会自动导入 components 目录中的所有组件,当你想使用组件时,不需要 import 了,直接使用即可

嵌套目录组件

如果您在嵌套目录中有一个组件,例如:

  1. components/
  2. --| base/
  3. ----| foo/
  4. ------| Button.vue
  1. <template>
  2. <div>
  3. <button>组件按钮测试</button>
  4. </div>
  5. </template>

组件的名称将基于其自己的路径目录和文件名,并删除重复的段。那么我们可以直接在其它地方使用:

  1. <BaseFooButton />

image.png :::info 为清楚起见,建议组件的文件名与其名称匹配。(因此,在上面的示例中,可以将Button.vue重命名为BaseFooButton.vue) ::: 如果只想根据组件的名称而不是路径自动导入组件,可以在 nuxt.config.ts配置

  1. export default defineNuxtConfig({
  2. components: [
  3. {
  4. path: '~/components',
  5. pathPrefix: false,
  6. },
  7. ],
  8. });

配置后上面的组件在使用时无需添加路径名

  1. <Button />

自定义扫描目录 全局组件前缀

默认情况下,仅扫描components目录。如果要添加其他目录,或更改在components目录的子文件夹中扫描组件的方式,则可以将其他目录添加到配置中

  1. export default defineNuxtConfig({
  2. srcDir: "src/",
  3. components: [
  4. {
  5. path: "~/components",
  6. extensions: [".vue", "ts"],
  7. pathPrefix: false,
  8. prefix: "Glo",
  9. },
  10. { path: "~/components/special-components", prefix: "Special" },
  11. ],
  12. });

上面的配置中给所有全局组件添加’Glo’前缀,前面例子中的 组件在使用时就要改为
再添加如下文件夹,根据配置,则Name组件在使用时应该添加 Special 前缀 <SpecialName />
image.png

动态组件

如果需要使用 Vue 的 <component :is="...">语法,则需要使用 Vue 提供的 resolveComponent 方法。

🙌🌰:
随便创建几个组件用于测试
image.png
组件里随便写点内容

  1. <template>
  2. <div>components A</div>
  3. </template>

使用动态组件示例:

  1. <template>
  2. <component :is="currentComponent ? currentComponent : 'div'" />
  3. <button @click="toggleComponent">切换组件</button>
  4. </template>
  5. <script lang="ts" setup>
  6. const currentComponent = shallowRef<Component | string>('')
  7. const TheA = resolveComponent('GloTheA') // Glo 是自定义的组件前缀
  8. const TheB = resolveComponent('GloTheB')
  9. const TheC = resolveComponent('GloTheC')
  10. const componentList = [TheA, TheB, TheC]
  11. let index = -1
  12. const toggleComponent = () => {
  13. index = index < 2 ? index + 1 : 0
  14. currentComponent.value = componentList[index]
  15. }
  16. </script>

image.png

image.png

动态导入 (懒加载组件)

态导入组件(也称为懒加载组件),只需在组件名称中添加Lazy前缀。如果不总是需要该组件,可以通过使用Lazy前缀,将组件代码的加载延迟到适当的时间,这有助于优化 JavaScript 包大小。

比较适合一些弹窗组件,通常需要点击事件才会打开弹窗

  1. <template>
  2. <div>
  3. <LazyMyModal v-model:open="isOpen" />
  4. </div>
  5. </template>

手动导入

如果希望或需要绕过 Nuxt 的自动导入功能,还可以显式地从#components导入组件。
前面动态组件的例子,除了使用 resolveComponent 方法,也可以改为手动导入组件

  1. <template>
  2. <component :is="currentComponent ? currentComponent : 'div'" />
  3. <button @click="toggleComponent">切换组件</button>
  4. </template>
  5. <script lang="ts" setup>
  6. import { GloTheA } from '#components'
  7. const currentComponent = shallowRef<Component | string>('')
  8. // const TheA = resolveComponent('GloTheA')
  9. const TheB = resolveComponent('GloTheB')
  10. const TheC = resolveComponent('GloTheC')
  11. const componentList = [GloTheA, TheB, TheC]
  12. let index = -1
  13. const toggleComponent = () => {
  14. index = index < 2 ? index + 1 : 0
  15. currentComponent.value = componentList[index]
  16. }
  17. </script>

nuxt3 内置组件

客户端组件

Nuxt 提供了 专门用于仅在客户端渲染组件的组件;
要仅在客户端导入组件,请在仅客户端插件中注册该组件。

  1. <template>
  2. <div>
  3. <ClientOnly>
  4. <!-- 此组件仅在客户端显示 -->
  5. <Comments />
  6. </ClientOnly>
  7. </div>
  8. </template>

路由出口组件

如果需要使用 pages 显示相关页面的话,需要使用路由出口组件:

  1. <template>
  2. <div>
  3. <NuxtLayout>
  4. <NuxtPage/>
  5. </NuxtLayout>
  6. </div>
  7. </template>

:::info 由于Nuxt 3在内部使用了,因此不能将设置为根元素。 :::

Props

是 Vue Router 中组件的封装。和一样接受 name 和 routeProps,额外还接受一个pageKey属性。

  • name

type:string
name 帮助 RouterView在匹配的路由记录的组件选项中使用相应的名称渲染组件。参考Vue Router的命名视图

  • route
  • type: RouteLocationNormalized

route是一个路由地址的所有组件都已被解析(如果所有组件都被懒加载)。参考的route属性

Nuxt 通过扫描和渲染pages目录中的所有 Vue 组件文件,自动解析nameroute

  • pageKey

type: ‘string’ | ‘function’
pageKey有助于组件被重新渲染的时候有更多的控制。
通过传递 static key, 组件在挂载时只呈现一次。

自定义 Props

也接受自定义的Props,如需要将值传递到子组件中时可以在子组件中声明 Props。

未定义Props的属性则可以通过 Vue 的透传 Attribute $attrs访问。
透传 Attribute

🙌🌰:
pages/parent.vue

  1. <template>
  2. <div>
  3. <h1>嵌套路由示例 - 父级 parent.vue 页面</h1>
  4. <NuxtPage page-key="static" title="myTitle" foobar="value" />
  5. </div>
  6. </template>

pages/parent/index.vue 或者 pages/parent/child.vue

  1. <template>
  2. <div>
  3. <h1>parent 目录 index.vue 页面 {{ $attrs }}</h1>
  4. </div>
  5. </template>
  6. <script setup>
  7. const props = defineProps({
  8. title: {
  9. type: String,
  10. default: '我是标题'
  11. }
  12. })
  13. console.log('🚀 ~ file: index.vue:13 ~ props:', props)
  14. const attrs = useAttrs()
  15. console.log(attrs)
  16. </script>

template 中可以使用 $attrs.foobar 获得 foobar 的值,script 中使用 vue 的 useAttrs() 方法。
image.png
image.png

布局组件

通过 组件为页面添加布局组件。

  1. <!-- ~/app.vue -->
  2. <template>
  3. <NuxtLayout>
  4. some page content
  5. </NuxtLayout>
  6. </template>

name prop

组件接受一个name prop,可以通过它来指定一个非默认的布局。它必须与 layouts 目录中的布局文件的名称匹配。

  1. <!-- ~/pages/index.vue -->
  2. <template>
  3. <NuxtLayout :name="layout">
  4. <NuxtPage />
  5. </NuxtLayout>
  6. </template>
  7. <script setup>
  8. const layout = 'custom' // 名称对应 layouts/custom.vue
  9. </script>

:::info 布局名称被规范化为kebab-case,如果布局文件被命名为 myLayout.vue,当使用名称属性传递给时,它将成为 my-layout :::

Layout and Transition

通过 渲染传入的内容,然后将其包裹在 Vue 的组件上以激活布局过渡。为了使其按预期工作,建议 不要作为页面组件的根元素。

Nuxt 提供了 组件来处理应用程序中任何类型的链接。是 Vue Router 组件和 HTML 标签的直接替代品。它智能地确定链接是内部的还是外部的,并通过可用的优化(预取、默认属性等)相应地呈现它,如外部链接会自动添加rel、target等属性。

使用<NuxtLink>组件链接到应用程序的另一个页面:

  1. <template>
  2. <NuxtLink to="/about">
  3. About page
  4. </NuxtLink>
  5. <!-- <a href="/about">...</a> (+Vue Router & prefetching) -->
  6. </template>
  1. <template>
  2. <NuxtLink to="https://twitter.com/nuxt_js" target="_blank">
  3. Nuxt Twitter
  4. </NuxtLink>
  5. <!-- <a href="https://twitter.com/nuxt_js" target="_blank" rel="noopener noreferrer">...</a> -->
  6. <NuxtLink to="https://discord.nuxtjs.org" target="_blank" rel="noopener">
  7. Nuxt Discord
  8. </NuxtLink>
  9. <!-- <a href="https://discord.nuxtjs.org" target="_blank" rel="noopener">...</a> -->
  10. <NuxtLink to="https://github.com/nuxt" no-rel>
  11. Nuxt GitHub
  12. </NuxtLink>
  13. <!-- <a href="https://github.com/nuxt">...</a> -->
  14. <NuxtLink to="/contact" target="_blank">
  15. Contact page opens in another tab
  16. </NuxtLink>
  17. <!-- <a href="/contact" target="_blank" rel="noopener noreferrer">...</a> -->
  18. </template>

Props

to:任何 URL 或来自 Vue Router 的路由对象
href:to的一个别名。如果和to一起使用,href将被忽略
target:应用于链接的目标属性值
rel:用于链接的rel属性值。对于外部链接,默认为 “noopener noreferrer”。
noRel:如果设置为 “true”,则没有rel属性将被添加到链接上。
activeClass:适用于链接激活时。与 Vue Router 的active-class在内部链接上的作用相同。默认为 Vue Router 的默认值是router-link-active。
exactActiveClass:链接精准激活时,应用于渲染的的 class。与Vue Router在内部链接上的exact-active-class的作用相同。默认为 Vue Router 的默认值是router-link-exact-active”。
replace:与内部链接上的 Vue Router 的
replace相同。
ariaCurrentValue:当链接激活时,传递给属性aria-current的值。与内部链接上的 Vue Router 的aria相同。
external:强制将链接视为外部(true)或内部(false)。
custom:<NuxtLink>是否应将其内容包装在<a>元素中。它允许完全控制链接的呈现方式以及单击时导航的工作方式。工作原理与 Vue Router 的custom相同。

自定义

可以通过使用 defineNuxtLink 创建自己的链接组件来覆盖<NuxtLink>默认值。

defineNuxtLink类型:

  1. defineNuxtLink({
  2. componentName?: string; // 定义的<NuxtLink>组件的名称
  3. externalRelAttribute?: string; // 应用于外部链接的默认rel属性值。默认为noopener-noreferrer。将其设置为''以禁用
  4. activeClass?: string; // 适用于链接激活时。与 Vue Router 的active-class在内部链接上的作用相同。默认为 Vue Router 的默认值是router-link-active。
  5. exactActiveClass?: string; // 链接精准激活时,应用于渲染的<a>的 class。与Vue Router在内部链接上的exact-active-class的作用相同。默认为 Vue Router 的默认值是router-link-exact-active"
  6. prefetchedClass?: string;
  7. trailingSlash?: 'append' | 'remove'
  8. }) => Component

在 components/MyNuxtLink.ts 定义自定义的

  1. export default defineNuxtLink({
  2. componentName: 'MyNuxtLink',
  3. externalRelAttribute: '',
  4. activeClass: 'active',
  5. exactActiveClass: 'exact-active'
  6. })

页面加载进度组件

Nuxt 提供组件在页面导航上显示当前页面的加载状态进度条。

添加到app.vue或layout组件中。

  1. <template>
  2. <NuxtLayout>
  3. <NuxtLoadingIndicator /> <!-- here -->
  4. <NuxtPage />
  5. </NuxtLayout>
  6. </template>

Props

  • color:加载条颜色
  • height:加载条高度,单位:px,默认值为:3
  • duration:加载条加载持续时间,单位:毫秒,默认值为:2000
  • throttle:显示加载条之前等待的时间,单位:毫秒,默认值为:200

    SEO 相关组件

    Nuxt 提供 <Title> <Base> <NoScript> <Style> <Meta> <Link> <Body> <Html> <Head>等内置组件。
    这些组件名称与 HTML 元素匹配,因此在模板中将它们大写非常重要 ```vue

```