如何修复watch未触发问题?有无替代useLazyAsyncData做字符串转JSON的方案?
问题修复与优化方案
一、watch未触发的核心原因
report是useLazyAsyncData返回的ref对象,虽然watch可以监听ref,但你用reactive()创建的reportJson直接被赋值覆盖(reportJson = JSON.parse(...)),这会丢失reactive对象的响应性引用,即使watch触发也无法正确更新数据。- 若API返回字符串为空或格式非法,也会导致后续逻辑中断,但优先解决响应性问题。
二、修复watch触发的代码调整
<template> <h1>Report</h1> <v-data-table :items="reportJson" :headers="headers" v-if="!pending" ></v-data-table> </template> <script setup> import { reactive, ref, watch } from 'vue'; import { useLazyAsyncData } from '#app'; const headers = reactive([ { title: "First Name", key: "first_name" }, { title: "Last Name", key: "last_name" }, { title: "Gender", key: "gender" }, ]); const { pending, data: report } = useLazyAsyncData("report", () => $fetch("https://random-api.com/report/hash123") ); // 用ref替代reactive,支持直接替换整个对象 const reportJson = ref([]); // 监听report变化,添加immediate处理初始加载完成后的赋值 watch(report, (newReport) => { if (newReport) { console.log("watch() called"); reportJson.value = JSON.parse(newReport); } }, { immediate: true }); </script>
三、更优的字符串后处理方案
无需使用watch,直接在请求回调中完成JSON转换,代码更简洁且避免响应性问题:
<template> <h1>Report</h1> <v-data-table :items="reportJson" :headers="headers" v-if="!pending" ></v-data-table> </template> <script setup> import { reactive } from 'vue'; import { useLazyAsyncData } from '#app'; const headers = reactive([ { title: "First Name", key: "first_name" }, { title: "Last Name", key: "last_name" }, { title: "Gender", key: "gender" }, ]); const { pending, data: reportJson } = useLazyAsyncData("report", async () => { const response = await $fetch("https://random-api.com/report/hash123"); // 直接在请求阶段完成转换,同时添加错误处理 try { return JSON.parse(response); } catch (e) { console.error("JSON解析失败", e); return []; } }); </script>
额外注意点
- 给
v-data-table加上v-if="!pending",避免数据未加载时渲染空表格; - 必须添加JSON解析的错误捕获,防止API返回异常字符串导致页面崩溃。
内容的提问来源于stack exchange,提问作者DevonDahon
相关产品推荐
相关产品推荐

