Nuxt 中有一些特殊的组件用法
异步组件
加 Lazy 前缀即可
<LazyMountainsList v-if="show" />
动态组件
方式一:使用 Vue 提供的 resolveComponent 函数
<script setup lang="ts">
const Demo1 = resolveComponent("Demo1");
const Demo2 = resolveComponent("Demo2");
const SomeComponent = ref(Demo1);
function change() {
SomeComponent.value = Demo2;
}
</script>
<template>
<div>
<button @click="change">切换到范例组件2</button>
<component :is="SomeComponent" />
</div>
</template>
方式二:从 #components 中导入组件(会绕过 Nuxt 的自动导入功能)
<script setup lang="ts">
import { Demo1, Demo2 } from "#components";
const SomeComponent = ref(Demo1);
function change() {
SomeComponent.value = Demo2;
}
</script>
<template>
<div>
<button @click="change">切换到范例组件2</button>
<component :is="SomeComponent" />
</div>
</template>
客户端组件
仅在客户端渲染的组件
方式一:在组件名后添加 .client 后缀
Comments.client.vue
- 若显式导入这些组件( 从 #components 导入除外),则仍是服务端渲染
- .client 组件仅在挂载后才会渲染。要在 onMounted() 的回调中访问渲染的模板,请在 onMounted() 钩子的回调中添加 await nextTick()。
方式二:使用 Nuxt3 内置的 <ClientOnly>
组件
<ClientOnly>
<!-- 此组件仅在客户端渲染 -->
<Comments />
</ClientOnly>
可按下方代码添加服务端渲染的内容 ( 如客户端完成渲染前,显示正在加载 )
<template>
<div>
<Sidebar />
<!-- 这将在服务器端渲染 "span" 元素 -->
<ClientOnly fallbackTag="span">
<!-- 此组件仅在客户端渲染 -->
<Comments />
<template #fallback>
<!-- 这将在服务器端渲染 -->
<p>Loading comments...</p>
</template>
</ClientOnly>
</div>
</template>
#fallback 是插槽写法,也可用 fallback 属性
<template>
<div>
<Sidebar />
<ClientOnly fallback-tag="span" fallback="加载评论中...">
<Comment />
</ClientOnly>
</div>
</template>
内置组件
<NuxtLayout>
用于渲染对应的布局,默认加载 default 布局
- name 属性可指定需加载的布局
<NuxtLayout name="custom">
<NuxtPage />
</NuxtLayout>
- 获取布局组件的 ref,需通过 ref.value.layoutRef
<script setup lang="ts">
const layout = ref()
function logFoo () {
layout.value.layoutRef.foo()
}
</script>
<template>
<NuxtLayout ref="layout" />
</template>
- 可向下传递自定义属性
<NuxtLayout name="custom" title="我是一个自定义布局">
<-- ... -->
</NuxtLayout>
具体页面的模板中可以通过 $attrs.title 获取,JS 中可通过 useAttrs().title 获取
- 为了达到预期的过渡效果,建议
<NuxtLayout />
不是页面组件的根元素
<template>
<div>
<NuxtLayout name="custom">
<template #header> 页面头部模板内容。 </template>
</NuxtLayout>
</div>
</template>
<NuxtPage>
是对 Vue Router 的 <RouterView>
组件的封装,用于渲染路由对应的页面。
- 通过传递 static 键,NuxtPage 组件在挂载时只会渲染一次
<template>
<NuxtPage page-key="static" />
</template>
- 获取页面组件的 ref,需通过 ref.value.pageRef
<script setup lang="ts">
const page = ref()
function logFoo () {
page.value.pageRef.foo()
}
</script>
<template>
<NuxtPage ref="page" />
</template>
- 可向下传递自定义属性
<NuxtPage :foobar="123" />
具体页面的模板中可以通过 $attrs.foobar 获取,JS 中可通过 useAttrs().foobar 获取
<NuxtLink>
是 Vue Router 的 <RouterLink>
组件和 HTML 的 <a>
标签的替代品。它能智能地确定链接是内部链接还是外部链接,并根据可用的优化(预加载、默认属性等)进行渲染。
<NuxtLink to="/about">
路由到内部页面
</NuxtLink>
<NuxtLink to="https://nuxtjs.org">
路由到外部网站
</NuxtLink>
<NuxtLink>
的完整属性列表和自定义<NuxtLink>
的方法,详见官网
<NuxtImg>
是原生<img>
标签的一个即插即用替代品,功能如下:
- 使用内置提供商优化本地和远程图像
- 将src转换为提供商优化的URL
- 根据width和height自动调整图像大小
- 在提供sizes选项时生成响应式尺寸
- 支持原生懒加载以及其他
<img>
属性
使用前,需先安装
npx nuxi@latest module add image
使用时,和<img>
标签一样
<NuxtImg src="/nuxt-icon.png" />
更多功能详见其官网 https://image.nuxt.com/usage/nuxt-img
<NuxtPicture>
是对原生picture标签的一种直接替代方式,在可能的情况下提供现代格式,如webp
用法几乎与 NuxtImg 相同,
<Teleport>
将一个组件传送到DOM中的不同位置,目前只支持传送到 body
<template>
<button @click="open = true">
打开模态框
</button>
<Teleport to="body">
<div v-if="open" class="modal">
<p>来自模态框的问候!</p>
<button @click="open = false">
关闭
</button>
</div>
</Teleport>
</template>
对于其他目标的客户端支持需要使用<ClientOnly>
包装器。
<template>
<ClientOnly>
<Teleport to="#some-selector">
<!-- 内容 -->
</Teleport>
</ClientOnly>
</template>
<NuxtLoadingIndicator>
在页面导航之间显示一个进度条。
<NuxtLayout>
<div>
<NuxtLoadingIndicator /> <!-- 在这里 -->
<NuxtPage />
</div>
</NuxtLayout>
属性如下:
- color: 进度条的颜色。可以设置为 false 来关闭显式的颜色样式。
- height: 进度条的高度,以像素为单位(默认为 3)。
- duration: 进度条的持续时间,以毫秒为单位(默认为 2000)。
- throttle: 进度条出现和隐藏的节流时间,以毫秒为单位(默认为 200)。
<NuxtErrorBoundary>
处理在其默认插槽中发生的客户端错误。
https://www.nuxt.com.cn/docs/api/components/nuxt-error-boundary
<ClientOnly>
客户端组件中已介绍
<DevOnly>
仅在开发环境中渲染的组件
<DevOnly>
<!-- 仅在开发环境中渲染此组件 -->
<LazyDebugBar />
<!-- 如果您需要在生产环境中进行替换 -->
<!-- 请确保使用 `nuxt preview` 进行测试 -->
<template #fallback>
<div><!-- 用于 flex.justify-between 的空 div --></div>
</template>
</DevOnly>
<NuxtWelcome>
展示 Nuxt 文档、源代码和社交媒体账号的链接,效果如下图
实验中的内置组件
<NuxtClientFallback>
其任何子组件在 SSR 中触发错误,则在客户端渲染其内容。
<!-- 此组件将在客户端渲染 -->
<NuxtClientFallback fallback-tag="span">
<Comments />
<BrokeInSSR />
</NuxtClientFallback>
<NuxtIsland>
渲染一个没有任何客户端JS的非交互式组件
https://www.nuxt.com.cn/docs/api/components/nuxt-island
其他
Nuxt 提供了<Title>、<Base>、<NoScript>、<Style>、<Meta>、<Link>、<Body>、<Html>和<Head>
组件,让你可以直接在组件的模板中与元数据进行交互。
<script setup lang="ts">
const title = ref('你好,世界')
</script>
<template>
<div>
<Head>
<Title>{{ title }}</Title>
<Meta name="description" :content="title" />
<Style type="text/css" children="body { background-color: green; }" />
</Head>
<h1>{{ title }}</h1>
</div>
</template>
添加组件库
详见官网