Vue3 Script Setup中v-for不渲染数据问题求助(对比Options API)
为什么Script Setup中v-for无法渲染数据,而Options API可以正常工作?
模板中使用v-for遍历string[]:
<div v-for="lang in data.translatedLanguages" class="translationTableBodyRow"> <div class="translationTableBodyCell">xx</div> <div class="translationTableBodyCell">{{ lang }}</div> <div class="translationTableBodyCell">10 %</div> <div class="translationTableBodyCell">Edit</div> </div>
可正常工作的Options API代码
<script lang="ts"> import axios, {isCancel, AxiosError} from 'axios'; import { defineComponent } from 'vue' export default defineComponent({ data() { return { data: { translatedLanguages: [] } } }, mounted() { axios.get("https://translation.colreminder.com/test/data.php?request=langTranslated").then(response => { console.log(response.request.response); this.data = JSON.parse(response.request.response) console.log(this.data.translatedLanguages); }); } }); </script>
无法渲染数据的Script Setup代码
<script lang="ts" setup> import axios, {isCancel, AxiosError} from 'axios'; import { onMounted, reactive } from 'vue'; import type { LanguagesTranslated } from './main'; var data: LanguagesTranslated = { translatedLanguages: [] }; onMounted(() => { axios.get("https://translation.colreminder.com/test/data.php?request=langTranslated").then(response => { console.log(response.request.response); data = JSON.parse(response.request.response); console.log(data.translatedLanguages); }); }); </script>
LanguagesTranslated接口定义
export interface LanguagesTranslated { translatedLanguages: string[]; }
问题原因
Script Setup中直接用var data声明的普通对象不具备响应式能力。Vue的响应式系统依赖reactive/ref来追踪数据变化,只有被包装成响应式的数据更新时,模板才会触发重新渲染。
而Options API里data()返回的对象会被Vue自动处理成响应式对象,所以修改this.data时模板能感知到变化并更新;但Script Setup中的普通变量无法触发响应式更新,哪怕你后续替换了整个对象引用,模板也不会同步渲染新数据。
修复方案
方案1:用reactive创建响应式对象,更新属性而非替换对象
<script lang="ts" setup> import axios from 'axios'; import { onMounted, reactive } from 'vue'; import type { LanguagesTranslated } from './main'; // 用reactive包装成响应式对象 const data = reactive<LanguagesTranslated>({ translatedLanguages: [] }); onMounted(() => { axios.get("https://translation.colreminder.com/test/data.php?request=langTranslated").then(response => { const resData = JSON.parse(response.request.response) as LanguagesTranslated; // 直接更新对象属性,保留响应式引用 data.translatedLanguages = resData.translatedLanguages; }); }); </script>
方案2:用ref创建响应式引用,允许替换整个对象
<script lang="ts" setup> import axios from 'axios'; import { onMounted, ref } from 'vue'; import type { LanguagesTranslated } from './main'; // 用ref创建响应式引用 const data = ref<LanguagesTranslated>({ translatedLanguages: [] }); onMounted(() => { axios.get("https://translation.colreminder.com/test/data.php?request=langTranslated").then(response => { // 替换ref的value属性 data.value = JSON.parse(response.request.response) as LanguagesTranslated; }); }); </script>
注意:使用ref时,模板中需要改为data.value.translatedLanguages,或者可以通过toRefs解构简化模板写法。
内容的提问来源于stack exchange,提问作者chrisonline
相关产品推荐
相关产品推荐

