tsconst ssrLoad = async () => {
  console.log("ssrLoad");
  // SSR 初始化查询单品列表
  const { data: res, error } = await useFetch<
    Result<PagePack<ProductOverview>>
  >("/api/product/getProductOverviewList", {
    method: "post",
    body: queryParam.value,
  });
  if (error.value) {
    navigateTo("/500");
  }
  if (res.value?.c == 200) {
    singlePage.value = res.value.d;
  } else {
    ElMessage.error(res.value?.m);
  }
};
await ssrLoad();
这是我使用 Nuxt3 时写在 <script setup> 中的一段代码,await ssrLoad(); 是为了用于 SSR 渲染页面调用的函数,但由于这么写,导致页面在输入框输入时会自动调用了 getProductOverviewList 接口。
但神奇的是,没有打印console.log("ssrLoad"); 这段日志;但更神奇的是,我去掉 await ssrLoad(); 这行代码就不会出现自动查询的这个现象,这是什么原因你知道吗?
经过排查以及咨询 ChatGPT,得知这个问题可能与 Vue 3 的 ref 响应性机制有关。在 Vue 3 中,<script setup> 的内容会在组件初始化时运行一次,并且响应式数据的更新会触发依赖它的计算属性、方法或其他响应式逻辑。因此,最终确定我的代码错误原因是:
queryParam.value 是响应式数据:如果 queryParam 是一个 ref 或 reactive 数据,那么当 queryParam.value 在输入框输入时改变时,会重新触发包含 await ssrLoad() 的响应式计算。这意味着任何在 ssrLoad 函数内访问的响应式变量都可能导致副作用。
再结合 没有打印console.log("ssrLoad"); 这段日志 这个神奇的现象,我们可知,当 queryParam.value 的值变化时,响应式触发了 useFetch 这个函数,而不是 ssrLoad 这个函数。
由以上问题原因可以得到一个简单的解决方案,那就是修改 queryParam 的定义方式,不再使用响应式数据,如下:
tsconst param = {
    pageNum: 1,
    pageSiez: 10
}
const queryParam = ref(param);
const ssrLoad = async () => {
  console.log("ssrLoad");
  // SSR 初始化查询单品列表
  const { data: res, error } = await useFetch<
    Result<PagePack<ProductOverview>>
  >("/api/product/getProductOverviewList", {
    method: "post",
    body: param,
  });
  if (error.value) {
    navigateTo("/500");
  }
  if (res.value?.c == 200) {
    singlePage.value = res.value.d;
  } else {
    ElMessage.error(res.value?.m);
  }
};
await ssrLoad();
经过上述修改,将初始条件独立为一个普通常量,不再是响应式的参数,即可解决该问题。
本文作者:DingDangDog
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!