Vue组件数据对象属性的行为与预期不符[已解决]

时间:2019-09-06 18:21:10

标签: vue.js vue-component

我有一个带有子组件的应用程序,该组件可调用api以获得球员的赛季统计数据。您单击播放器名称,然后我将从父组件向孩子发出点击事件。问题是当您从父级单击“播放器名称”时,子级组件的所有实例都会显示出来。我只想要一个球员。我以为是因为通过在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
  })
};

1 个答案:

答案 0 :(得分:1)

所提供的代码实际上并未调用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: function() {
  EventBus.$on("showPlayerTemplateClicked", this.onShowPlayerTemplateClicked);
},

with方法:

methods: {
  onShowPlayerTemplateClicked: function(playerId) {
    if (playerId === this.props_player_id) {
      this.showComponent = !this.showComponent;
    }
  }
}

假定玩家ID是唯一的,应该足以使其正常工作。

但是...

  1. 选择事件总线将数据传递给孩子似乎是一个糟糕的选择。有几种方法可以完成此操作。一种方法是仅在显示时创建它(外部v-if)。另一个是使用道具。还有一种方法是使用ref对该子对象调用方法。
  2. 我不了解您的代码如何切换任何内容。 this中侦听器的mounted值将不是组件。我已经通过将其移至Vue可以正确绑定的方法来修复该问题。将其移至方法的另一个原因是,它允许您在销毁组件时删除侦听器。
  3. v-if:showComponent无关紧要。我认为应该是v-if="showComponent"
  4. 您的<tr>元素似乎是<div>元素的直接子代。这不是表格的正确HTML。