You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Vue3 Script Setup中如何正确显示异步获取的对象数据?

Vue3 Script Setup 异步请求数据渲染报错解决方案

问题根源分析

你遇到的报错本质是异步请求未完成时,模板直接访问了未初始化的深层属性,而普通变量无法触发响应式更新导致页面不渲染。下面逐个分析你的写法问题,并给出修正方案:


1. ref() 用法的问题与修正

你的代码里用了数组类型的ref,但初始渲染时movie[0]是undefined,直接访问movie[0].original_title会触发Cannot read properties of undefined错误。

修正方案:
不需要用数组存储单个对象,直接用ref(null)初始化,同时在模板中通过v-if或可选链?.避免报错:

<script setup>
import { ref } from 'vue'
import { useRoute } from 'vue-router'

const route = useRoute()
const movie = ref(null)

const getMovieData = async () => {
  try {
    const data = await getDetail('movie', route.params.id)
    movie.value = data
  } catch (e) {
    console.log(e)
  }
}

getMovieData()
</script>

<template>
  <!-- 方案1:用v-if确保数据存在后再渲染 -->
  <h1 v-if="movie">{{ movie.original_title }}</h1>
  
  <!-- 方案2:用可选链操作符,属性不存在时返回undefined,无报错 -->
  <!-- <h1>{{ movie?.original_title }}</h1> -->
</template>

2. reactive() 用法的问题与修正

初始时movie.data为null,模板直接访问movie.data.original_title会触发Cannot read properties of null错误,和ref的问题本质一致。

修正方案:
在模板中判断数据是否存在,或者使用可选链:

<script setup>
import { reactive } from 'vue'
import { useRoute } from 'vue-router'

const route = useRoute()
const movie = reactive({
  data: null
})

const getMovieData = async () => {
  try {
    const data = await getDetail('movie', route.params.id)
    movie.data = data
  } catch (e) {
    console.log(e)
  }
}

getMovieData()
</script>

<template>
  <!-- 方案1:v-if判断数据存在 -->
  <h1 v-if="movie.data">{{ movie.data.original_title }}</h1>
  
  <!-- 方案2:可选链操作符 -->
  <!-- <h1>{{ movie.data?.original_title }}</h1> -->
</template>

3. 普通变量用法的问题与修正

普通变量不具备Vue的响应式能力,即使异步请求完成后赋值movie = data,页面也不会触发重新渲染,所以无法显示数据。必须使用ref或reactive声明响应式变量,参考上面两种修正方案即可。


核心总结

  • 异步数据渲染必须处理初始值为空的场景,通过v-if或可选链?.避免访问未定义属性的报错
  • 只有ref/reactive声明的变量才能触发Vue的响应式更新,普通变量无法用于动态渲染数据

内容的提问来源于stack exchange,提问作者Yunus Emre Arslan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 01:45:34