You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Nuxt 3中如何修复基于滚动条件类的Hydration错误?

修复Navbar组件的Hydration类不匹配问题

我有一个顶部Navbar组件,逻辑为:用户完全未滚动(Y偏移量=0)时不显示桌面端阴影,滚动距离越远阴影越大。相关代码如下:

滚动阴影类计算的Composable代码

export function getShadowClassBasedOnScrollingOffset(
  alwaysDisplayOnMobile: boolean = true,
): string {
  const { y } = useWindowScroll();

  let classList = "";

  if (alwaysDisplayOnMobile) {
    classList += "shadow ";
  }

  if (y.value < 5) {
    classList += "md:shadow-none";
    return classList;
  }

  if (y.value < 10) {
    classList += "md:shadow";
    return classList;
  }

  classList += "md:shadow-lg";
  return classList;
}
// Setup
const getShadowClass = computed(() => {
  return props.displayShadow ? getShadowClassBasedOnScrollingOffset(true) : "";
});
<template>
  <div
    class="w-full bg-white | px-4 md:px-0 py-4 transition"
    :class="getShadowClass"
  >
    <!-- Navbar内容 -->
  </div>
</template>

收到的Hydration警告

Hydration class Mismatch on :

  • rendered on server: class="w-full bg-white | px-4 md:px-0 py-4 transition shadow md:shadow-none"
  • expected on client: class="w-full bg-white | px-4 md:px-0 py-4 transition shadow md:shadow-lg"

问题原因

服务端渲染时没有浏览器环境,useWindowScroll的y.value默认是0,因此服务端会渲染md:shadow-none类;但客户端初始化时,如果页面并非从顶部开始(比如用户刷新时处于滚动状态),y.value会是实际滚动值,导致客户端渲染的类与服务端不一致,触发Hydration不匹配警告。

修复方案

核心思路是让服务端和客户端初始渲染的类完全一致,服务端固定返回未滚动状态的类,客户端挂载后再根据实际滚动值更新类。

方案1:在组件中添加客户端状态判断

修改Navbar组件的setup逻辑,确保服务端返回与初始渲染一致的类:

import { ref, computed, onMounted } from 'vue';

// Setup
const isClient = ref(false);
onMounted(() => {
  // 标记客户端已挂载
  isClient.value = true;
});

const getShadowClass = computed(() => {
  if (!props.displayShadow) return '';
  
  // 服务端渲染时返回固定的未滚动状态类
  if (!isClient.value) {
    return 'shadow md:shadow-none';
  }
  
  // 客户端挂载后再根据滚动计算类
  return getShadowClassBasedOnScrollingOffset(true);
});

方案2:修改Composable,加入客户端环境判断

直接在Composable中判断是否处于客户端环境,服务端时返回固定类:

export function getShadowClassBasedOnScrollingOffset(
  alwaysDisplayOnMobile: boolean = true,
): string {
  const isClient = typeof window !== 'undefined';
  const { y } = useWindowScroll();

  let classList = "";

  if (alwaysDisplayOnMobile) {
    classList += "shadow ";
  }

  // 服务端时直接返回未滚动状态类
  if (!isClient) {
    classList += "md:shadow-none";
    return classList.trim();
  }

  if (y.value < 5) {
    classList += "md:shadow-none";
    return classList.trim();
  }

  if (y.value < 10) {
    classList += "md:shadow";
    return classList.trim();
  }

  classList += "md:shadow-lg";
  return classList.trim();
}

两种方案都能确保服务端和客户端初始渲染的类一致,Hydration完成后客户端再根据实际滚动状态更新阴影类,既保留SSR的优势,又解决了警告问题。


内容的提问来源于stack exchange,提问作者xTheWolf

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 03:27:23