我正在制作一个简单的“电子邮件确认”页面。 它从 URL 获取确认密钥,向 API 发送 POST 请求,该请求返回
true
或不返回任何内容。
如果密钥正确,API 从数据库中删除并返回 true
,以便页面可以显示成功消息:
// pages/confirm/[key].vue
<script setup>
const route = useRoute();
const key = route.params.key;
const confirmed = ref(false);
try
{
const result = await $fetch('/api/confirm', {
method: 'post',
body: { key: key },
});
confirmed.value = !!result;
} catch {}
</script>
<template>
<div v-if="confirmed">Email confirmed!</div>
</template>
问题是,当我在浏览器中使用在 URL 中传递的正确密钥打开页面时,我只能看到“电子邮件已确认”消息几毫秒,然后它就会消失,并在控制台中显示“水合不匹配”警告。
据我了解,Nuxt 在服务器上呈现页面,其中页面有“电子邮件已确认”消息。但是,在有关确认密钥的 API 调用信息从数据库中删除后,当浏览器渲染时,它再次调用 API,这次它得到一个空响应(因为不再有这样的电子邮件确认密钥)并删除成功消息。
我该如何修复它? 也许有一种方法可以只进行一次 API 调用或以某种方式保存其结果? 我是 Nuxt 的新手,我真的不知道如何正确处理这个“双重渲染”的事情......
最简单的方法是将
pages/confirm/[key].vue
指定为 nuxt.config.ts
中的 CSR 页面组件
export default defineNuxtConfig({
routeRules: {
'confirm-key': {
ssr: false
}
}
});
由于页面仅在客户端呈现,因此
$fetch
只会在用户的浏览器中执行
useLazyFetch
代替$fetch
,而且,你需要将<div>
包裹在<client-only>
中
// pages/confirm/[key].vue
<script setup>
const route = useRoute();
const key = route.params.key;
const confirmed = ref(false);
try
{
const result = await useLazyFetch('/api/confirm', {
method: 'post',
body: { key: key },
});
confirmed.value = !!result;
} catch {}
</script>
<template>
<client-only>
<div v-if="confirmed">Email confirmed!</div>
</client-only>
</template>