Vue3组件传递多v-model props获取足球API数据问题排查
核心问题:Prop传递错误导致数据未正确接收
1. 父组件状态定义错误
你把selectedLeague和selectedTeam定义成了props,但这两个是父组件自身维护的状态,应该放在data中:
// Teams.vue 中data修改为: data() { return { headerShow: false, leagues: [], teams: [], selectedLeague: null, // 移到data里 selectedTeam: null // 移到data里 } } // 删除原props中的selectedLeague和selectedTeam
2. 子组件Prop定义错误
子组件把需要的两个prop嵌套在了data属性里,应该直接定义独立的prop:
// TeamStatistics.vue 中props修改为: props: { selectedLeague: { type: String, required: true }, selectedTeam: { type: String, required: true } }
3. 父组件传递Prop的方式错误
不需要用v-model(v-model用于双向绑定,需子组件触发update事件),直接用普通prop传递即可,且模板中无需加this.:
<!-- Teams.vue 中TeamStatistics组件修改为: --> <TeamStatistics v-if="selectedTeam" :key="selectedTeam.teamId" :selected-league="selectedLeague.id" :selected-team="selectedTeam.teamId" />
数据请求逻辑优化
1. 子组件监听Prop变化,动态更新数据
当前子组件仅在mounted时请求一次数据,当父组件的选中项变化时,需重新获取统计数据,添加watch并抽离请求方法:
// TeamStatistics.vue 中添加watch和方法: watch: { selectedTeam: { immediate: true, handler() { this.fetchTeamStatistics() } }, selectedLeague: { immediate: true, handler() { this.fetchTeamStatistics() } } }, methods: { fetchTeamStatistics() { this.teamStatistics = [] const optionsTeams = { method: 'GET', url: 'https://api-football-v1.p.rapidapi.com/v3/teams/statistics', params: { league: this.selectedLeague, season: '2022', team: this.selectedTeam }, headers: { 'X-RapidAPI-Key': 'XXXXXXXXXXXXXX', 'X-RapidAPI-Host': 'api-football-v1.p.rapidapi.com' } }; axios.request(optionsTeams).then(response => { const stats = response.data.response this.teamStatistics.push({ name: stats.team.name, photo: stats.team.logo, form: stats.form, played: stats.fixtures.played.total, wins: stats.fixtures.wins.total, draws: stats.fixtures.draws.total, loses: stats.fixtures.loses.total, goalsFor: stats.goals.for.total.total, goalsAgainst: stats.goals.against.total.total, biggestWinStreak: stats.biggest.streak.wins, biggestWins: stats.biggest.wins, }) // 空值处理需放在异步回调内,确保数据已存在 this.teamStatistics.forEach(o => { Object.keys(o).forEach(k => { if (o[k] === null) { o[k] = 'No info' } }) }) }).catch(error => { console.error(error) }) } }, mounted() { // 用ref替代原生DOM操作,符合Vue规范 this.$refs.popup.style.visibility = 'hidden'; setTimeout(() => { this.$refs.popup.style.visibility = 'visible'; }, 600); }
模板中添加ref:
<!-- TeamStatistics.vue 模板修改: --> <div class="popup" ref="popup">
2. 父组件异步请求逻辑修正
父组件中console.log(this.leagues)会在axios请求完成前执行,导致打印空数组,需移到回调内:
// Teams.vue mounted中的axios请求修改: axios.request(options).then(response => { for (let i = 0; i < response.data.response.length; i++) { this.leagues.push({ name: response.data.response[i].league.name, id: response.data.response[i].league.id.toString(), displayLeague: `${response.data.response[i].league.name + ', ' + response.data.response[i].country.name}` }) } console.log(this.leagues) // 移到这里 }).catch(function (error) { console.error(error); });
其他代码优化建议
- 模板中移除
this.:Vue模板可直接访问组件实例属性,比如{{ teamStatistics[0].name }}即可。 - 空值安全渲染:用可选链操作符避免数组为空时报错,比如
{{ teamStatistics[0]?.name || 'No info' }}(需Vue 2.6+或Vue 3支持)。 - 数组清空方式:父组件中
this.teams.length = 0可替换为this.teams = [],更直观。 - 方法逻辑修正:父组件
dropdownShouldOpen方法中的this.league应为this.selectedLeague,否则逻辑不生效。 - 组件name规范:组件name无需加
.vue,比如name: "Teams"即可。
内容的提问来源于stack exchange,提问作者Remik00
相关产品推荐
相关产品推荐

