Skip to content

条件渲染

ClientOnly

仅在客户端渲染内容,SSR 时显示 fallback 内容。

vue
<template>
  <ClientOnly>
    <!-- 仅客户端渲染 -->
    <MapComponent />

    <!-- SSR 时的 fallback -->
    <template #fallback>
      <div class="loading">加载地图中...</div>
    </template>
  </ClientOnly>
</template>

Props

Prop类型默认值说明
hydratebooleantrue是否参与 Hydration

适用场景

场景示例
使用 windowdocument 的组件地图、图表库
第三方库不支持 SSR某些 jQuery 插件
避免 Hydration 不匹配动态生成的 DOM

完整示例:集成地图组件

vue
<template>
  <div class="map-container">
    <ClientOnly>
      <LeafletMap :center="center" :zoom="12" />
      <template #fallback>
        <div class="map-placeholder">
          <span class="spinner" />
          <p>地图加载中...</p>
        </div>
      </template>
    </ClientOnly>
  </div>
</template>

hydrate 属性

vue
<template>
  <!-- 不参与 Hydration(纯客户端渲染,不比较 SSR 输出) -->
  <ClientOnly :hydrate="false">
    <BrowserAnimation />
  </ClientOnly>
</template>

INFO

️ 使用 <ClientOnly> 会导致内容不被搜索引擎抓取 对于 SEO 重要的内容,应避免包裹在此组件中


DevOnly

仅在开发环境渲染内容,生产构建时完全移除(零代码体积)。

vue
<template>
  <DevOnly>
    <DebugPanel />
    <PerformanceMonitor />
  </DevOnly>
</template>

适用场景

场景说明
调试面板开发时显示组件状态
性能监控开发时显示渲染时间
模拟数据开发时使用假数据
开发辅助工具仅开发环境需要的 UI

完整示例:调试信息面板

vue
<template>
  <div>
    <h1>用户列表</h1>
    <UserList :users="users" />

    <!-- 仅开发环境显示 -->
    <DevOnly>
      <div class="debug-panel">
        <p>API 响应时间: {{ responseTime }}ms</p>
        <p>用户数量: {{ users.length }}</p>
        <pre>{{ JSON.stringify(users[0], null, 2) }}</pre>
      </div>
    </DevOnly>
  </div>
</template>

TIP

<DevOnly> 在生产构建中会被 Tree-shaking 完全移除 不会有任何性能开销。比 v-if="import.meta.dev" 更优雅


NuxtIsland

服务端组件,仅在服务端渲染为纯 HTML,客户端不 Hydration(无 JS 发送到浏览器)。

vue
<template>
  <!-- 渲染为纯 HTML,无 JS -->
  <NuxtIsland name="Counter" :props="{ initial: 0 }" />
</template>

创建服务端组件

components/ 下创建 .server.vue 文件:

vue
<!-- app/components/Counter.server.vue -->
<script setup lang="ts">
const props = defineProps<{ initial: number }>()
const count = ref(props.initial)
</script>

<template>
  <div>Count: {{ count }}</div>
</template>

Props

Prop类型说明
namestring服务端组件名称
propsobject传递给组件的 Props

服务端组件 vs 普通组件

特性服务端组件 (.server.vue)普通组件 (.vue)
渲染位置仅服务端服务端 + 客户端
Hydration❌ 不参与✅ 参与
JS 体积0 bytes包含组件逻辑
交互性❌ 无交互✅ 可交互
响应式❌ 无响应式✅ 响应式
适用场景纯展示、静态内容需要交互的组件

实际应用:纯展示型博客摘要

vue
<!-- app/components/BlogSummary.server.vue -->
<script setup lang="ts">
const props = defineProps<{ postId: number }>()
// 可以在服务端直接查询数据库
const post = await queryPost(props.postId)
</script>

<template>
  <article>
    <h2>{{ post.title }}</h2>
    <p>{{ post.excerpt }}</p>
    <time>{{ post.date }}</time>
  </article>
</template>
vue
<!-- 在页面中使用 -->
<template>
  <div>
    <NuxtIsland name="BlogSummary" :props="{ postId: 1 }" />
    <NuxtIsland name="BlogSummary" :props="{ postId: 2 }" />
  </div>
</template>

INFO

️ 服务端组件不支持交互(无 JS) 适合纯展示内容。如果需要交互,请使用普通组件或配合 <ClientOnly>

基于 Nuxt 4 官方文档整理编写