vue.js - Vue 组件数据对象属性的行为不符合预期 [已解决]
问题描述
我有一个带有子组件的应用程序,它调用 api 以获取球员的赛季统计数据。您单击玩家姓名,我会从父组件向子组件发出单击事件。问题是当您从父级单击 Players name 时,子组件的所有实例都会显示出来。我只想要一个球员。我想是因为我通过在 child 中切换 this.showComponent 为每个孩子都有一个 showComponent 实例会得到我预期的行为,但没有。代码:父-
methods: {
emitPlayerSeasonStatsClicked: function(event) {
const target = event.target;
EventBus.$emit("showPlayerTemplateClicked", target);
}
},
template: `
<div v-for="playerStats in props_box_game_scores[index].data.gameboxscore.awayTeam.awayPlayers.playerEntry">
<tr v-if="playerStats.player.Position === 'P'" class="d-flex" v-bind:data-player-id="playerStats.player.ID">
<td class="col-4 justify-content-center" scope="row" title="Click for Season Stats">
{{playerStats.player.FirstName}} {{playerStats.player.LastName}}
<span v-if="playerStats.stats.Wins['#text'] === '1'">(W)</span>
<span v-else-if="playerStats.stats.Losses['#text'] === '1'">(L)</span>
<span v-else-if="playerStats.stats.Saves['#text'] === '1'">(S)</span>
</td>
<td class="col-2 justify-content-center" justify-content="center">
{{playerStats.stats.InningsPitched['#text']}}</td>
<td class="col-2 justify-content-center">{{playerStats.stats.RunsAllowed['#text']}}</td>
<td class="col-2 justify-content-center">{{playerStats.stats.PitcherStrikeouts['#text']}}</td>
<td class="col-2 justify-content-center">{{playerStats.stats.EarnedRunAvg['#text']}}
</td>
</tr>
<pitcher-season-stats v-bind:props_player_id="playerStats.player.ID"></pitcher-season-stats>
</div>
孩子-
cumlativeStats: Vue.component("player-season-stats", {
props: ["props_player_id"],
data: function() {
return {
Hits: "",
HR: "",
RBI: "",
BattingAvg: "",
showComponent: false
};
},
mounted: function() {
EventBus.$on("showPlayerTemplateClicked", function(data) {
this.showComponent = !this.showComponent;
});
},
methods: {
retrievePlayerStats: function(playerId) {
const url = `https://api.mysportsfeeds.com/v1.2/pull/mlb/2019-regular/cumulative_player_stats.json?player=`;
const params = {
playerstats: "AB,H,HR,RBI,AVG",
force: true
};
...
template: `
<tr class="d-flex" v-if:showComponent>
<td @click="retrievePlayerStats(props_player_id)" class="col-4 justify-content-center" scope="row">
Season Stats</td>
</td>
<td class="col-2 justify-content-center" justify-content="center">
{{ Hits }}</td>
<td class="col-2 justify-content-center">{{ HR }}</td>
<td class="col-2 justify-content-center"> {{ BattingAvg }}</td>
<td class="col-2 justify-content-center">{{ RBI }}</td>
</tr>
` // End template
})
欢迎任何建议。抱歉格式化。
**
更新的工作解决方案:
**
家长:
methods: {
emitPlayerSeasonStatsClicked: function($event) {
let playerId = $event.target.dataset.playerId;
EventBus.$emit("showPlayerTemplateClicked", playerId);
}
}
....
<table @click="emitPlayerSeasonStatsClicked($event)" class="table table-striped table-bordered table-hover table-sm collapse" v-bind:class="'multi-collapse-' + index">
<tr v-if="playerStats.stats.AtBats['#text'] > 0" class="d-flex">
<td class="col-4 justify-content-center" :data-player-id='playerStats.player.ID' scope="row" title="Click for Season Stats">
{{playerStats.player.FirstName}} {{playerStats.player.LastName}} ({{playerStats.player.Position}})</td>
孩子:
mounted: function() {
EventBus.$on(
"showPlayerTemplateClicked",
this.onShowPlayerTemplateClicked
);
},
methods: {
onShowPlayerTemplateClicked: function(playerId) {
if (playerId === this.props_player_id) {
this.loading = true;
this.showComponent = !this.showComponent;
this.retrievePlayerStats(playerId);
}
},
template: `
<transition name="fade">
<tr class="d-flex" v-if="showComponent">
<td v-if="!loading" class="col-4 justify-content-center" scope="row">
Season Stats</td>
</td>
<td class="col-2 justify-content-center" justify-content="center">
{{ Hits }}</td>
<td class="col-2 justify-content-center">{{ HR }}</td>
<td class="col-2 justify-content-center"> {{ BattingAvg }}</td>
<td class="col-2 justify-content-center">{{ RBI }}</td>
</tr>
</transition>
` // End template
})
};
解决方案
提供的代码实际上并没有调用emitPlayerSeasonStatsClicked
,但我认为应该继续<td>
包含名称。
如果你这样写点击监听器:
<td
class="col-4 justify-content-center"
scope="row"
title="Click for Season Stats"
@click="emitPlayerSeasonStatsClicked(playerStats.player.ID)"
>
然后将 id 作为事件总线发出的事件的一部分包含在内:
emitPlayerSeasonStatsClicked: function(playerId) {
EventBus.$emit("showPlayerTemplateClicked", playerId);
}
在mounted中听这个将是:
mounted: function() {
EventBus.$on("showPlayerTemplateClicked", this.onShowPlayerTemplateClicked);
},
用方法:
methods: {
onShowPlayerTemplateClicked: function(playerId) {
if (playerId === this.props_player_id) {
this.showComponent = !this.showComponent;
}
}
}
假设玩家 ID 是唯一的,应该足以让它工作。
然而...
- 将数据传递给孩子的事件总线的选择似乎很糟糕。有几种方法可以做到这一点。一种方法是仅在显示时创建它(外部
v-if
)。另一个是使用道具。还有一个是使用 refs 来调用孩子的方法。 - 我不明白你的代码是如何切换任何东西的。
this
监听器的值mounted
不会是组件。我已经通过将它移动到一个方法来解决这个问题,Vue 将正确绑定该方法。将其移至方法的另一个原因是它允许您在组件被销毁时删除侦听器。 v-if:showComponent
不是一回事。我认为应该是v-if="showComponent"
。- 您的
<tr>
元素似乎是元素的直接子<div>
元素。这不是表格的正确 HTML。
推荐阅读
- python - 计算具有两个条件的数据框列的所有组合的乘积
- python - 烧瓶如何在html模板中使用python内置函数(Jinja 2)
- javascript - 为相关下拉选择设置默认值
- javascript - 带有“Console.log()”的执行上下文
- generics - TypeShape 和动态泛型
- mulesoft - Mule 4 中的 maxConcurrency
- excel - 修剪字符串提取变长字符串的部分
- html - 如何在不更改 HTML 的情况下通过 div 中的链接使 div 可点击
- python - 一个网站几天后停止工作,当我用scrapy刮它时给我一个弱连接,我无法刮取数据
- azure-synapse - 无法在 SSMS 上访问 Azure Synapse Spark Pool 数据库