Nuxt 3使用shift()时出现Hydration文本不匹配错误求助
问题原因
你遇到的 hydration 不匹配错误,核心问题出在直接修改了原数组:
data.shift()是会改变原数组的方法,服务端渲染时先执行一次,删掉数组第一个元素;- 客户端hydrate阶段会复用服务端传过来的已被shift过的数组,然后又执行一次
data.shift(),相当于数组被连续删了两次; - 这就导致服务端渲染出的
block1内容,和客户端hydrate时的block1内容完全不一致,触发了Nuxt的 hydration 校验错误。
另外,直接修改props里的数据也是Vue的禁忌,props是单向数据流,子组件不应直接修改。
修复方案
有两种靠谱的解决方式,按需选择:
方案一:子组件内复制数组再操作
不要直接使用props的原数组,先做浅拷贝,再对拷贝后的数组进行修改,这样服务端和客户端各自操作独立的数组副本,不会互相影响:
<script setup> defineComponent({ name: 'ChildComponent' }) const props = defineProps<UILayoutCategory>(); // 先拷贝原数组,避免修改原数据 const data = [...props.data]; data.shift(); const block1 = data.slice(0,4); </script> <template> <div class="layout"> {{ block1[0].title }}--{{ block1.length }} </div> </template>
方案二:父组件获取数据时提前处理
既然需要在服务端完成数据处理,最好在获取数据的环节就处理好,再传给子组件,这样前后端只用处理一次数据,从根源避免不一致:
<script setup> const { data: loadedData, error } = await useAsyncData('posts', async () => { const res = await $fetch(`/api/posts`, { method: 'GET' }); // 提前处理数据:跳过第一个元素,直接截取前4个(等价于shift后slice(0,4)) const processedData = res.data.slice(1, 5); return { data: processedData }; }); </script> <template> <div class="page-container"> <ChildComponent :data="loadedData.data" /> </div> </template>
此时子组件可直接使用处理好的数据,无需再修改:
<script setup> defineComponent({ name: 'ChildComponent' }) const props = defineProps<UILayoutCategory>(); const block1 = props.data; </script> <template> <div class="layout"> {{ block1[0].title }}--{{ block1.length }} </div> </template>
额外注意点
- 永远不要直接修改Vue的props数据,单向数据流要求子组件只能读取props,如需修改应通过emit通知父组件;
- 数组操作要区分修改原数组的方法(如shift、pop、splice、push)和返回新数组的方法(如slice、filter、map),优先使用返回新数组的方法,避免副作用。
内容的提问来源于stack exchange,提问作者Evgeny Anisimov
相关产品推荐
相关产品推荐

