Vue.js生产构建时Vite.config配置异常致数据获取失败问题
Vue生产构建后API请求失败并报错"Cannot read properties of undefined (reading 'length')"
问题原因分析
movie对象被完全覆盖导致自定义属性丢失
在API请求回调中执行this.movie = response.data;,直接用接口返回的电影数据替换了初始化时包含charactersData/planetsData等自定义数组的movie对象。接口返回的原始数据没有这些自定义属性,因此模板中读取movie.charactersData.length时,charactersData为undefined,触发报错。生产环境API请求路径无效
开发环境正常是因为隐性的代理配置(但你的vite.config.js未显式配置),生产环境部署后,相对路径api/films/xxx会指向当前域名下的无效路径(如https://star-wars-f0f14.web.app/api/films/xxx),导致API请求失败,数据无法加载。
解决方案
1. 合并接口数据而非覆盖movie对象
保留初始化时的自定义数组属性,用Object.assign将接口返回的数据合并到现有movie对象中:
// 替换原有的this.movie = response.data; Object.assign(this.movie, response.data);
2. 配置Vite代理与axios基础路径
修改vite.config.js,添加开发环境代理:
import { fileURLToPath, URL } from 'node:url' import { defineConfig } from 'vite' import vue from '@vitejs/plugin-vue' export default defineConfig({ plugins: [vue()], resolve: { alias: { '@': fileURLToPath(new URL('./src', import.meta.url)) } }, server: { proxy: { '/api': { target: 'https://swapi.dev/api', changeOrigin: true, rewrite: (path) => path.replace(/^\/api/, '') } } } })
全局配置axios的baseURL(如在main.js中):
import axios from 'axios' // 根据环境自动切换请求基础路径 axios.defaults.baseURL = import.meta.env.PROD ? 'https://swapi.dev/api' : '/api'
3. 模板添加可选链兜底判断
在v-if条件中使用可选链操作符,避免属性不存在时报错:
<template v-if="movie.charactersData?.length && movie.planetsData?.length && movie.starshipsData?.length && movie.vehiclesData?.length && movie.speciesData?.length">
4. 优化Promise请求逻辑(可选)
将多个独立的Promise.all合并,同时处理空数组场景,避免无效请求:
mounted() { window.scrollTo(0, 0) axios.get(`films/${this.id}`) .then(response => { Object.assign(this.movie, response.data); // 批量处理关联数据请求 const handleDataFetch = (urls, targetKey) => { if (!urls?.length) return Promise.resolve([]); return Promise.all(urls.map(url => axios.get(url))) .then(resps => this.movie[targetKey] = resps.map(r => r.data)) .catch(err => console.error(err)); } // 并行发起所有请求 Promise.all([ handleDataFetch(this.movie.characters, 'charactersData'), handleDataFetch(this.movie.planets, 'planetsData'), handleDataFetch(this.movie.starships, 'starshipsData'), handleDataFetch(this.movie.vehicles, 'vehiclesData'), handleDataFetch(this.movie.species, 'speciesData') ]) }) .catch(error => console.log(error)); }
内容的提问来源于stack exchange,提问作者Neron Godfather
相关产品推荐
相关产品推荐

