将v-model props与Vue 3组件相乘以获取API断点

w8biq8rn  于 2022-11-25  发布在  Vue.js
关注(0)|答案(1)|浏览(206)

我正在尝试提取子组件中的API断点
组件是为我的足球网络应用程序制作的。
中断点来自:api-football
如何将多个属性值传递到组件中?
在调试过程中,只有第二个道具在父组件中被读取(在本例中为(league))。

错误:

  1. https://api-football-v1.p.rapidapi.com/v3/teams?league=39&season=2022
    如果你有额外的时间,你可以评论一些代码审查有关它。我正在学习Vue。

团队版本(父级):

<template>
  <main id="Home-page">
    <UserPanel/>

    <Transition name="bounce">
      <h1 v-if="headerShow" class="welcome-header">
        Team statistics
      </h1>
    </Transition>

    <label class="label">Select league</label>
    <div class="selector">
      <v-select
          v-model="selectedLeague"
          :dropdown-should-open="dropdownShouldOpen"
          :options="leagues"
          label="displayLeague"
          placeholder="Select a league"
      />
    </div>

    <div v-show="selectedLeague">
      <label class="label">Select team</label>
      <div class="selector">
        <v-select
            v-model="selectedTeam"
            :dropdown-should-open="isLeagueSelected"
            :options="teams"
            label="teamName"
            placeholder="Select a team"
        />
      </div>
    </div>

    <TeamStatistics
        v-if="this.selectedTeam"
        :key="this.selectedTeam"
        v-model:selectedLeague="this.selectedLeague.id"
        v-model:selectedTeam="this.selectedTeam.teamId"
    />
  </main>
</template>

<script>
import UserPanel from "../components/UserPanel.vue";
import TeamStatistics from "../components/TeamStatistics.vue";
import axios from "axios";

export default {
  name: "Teams.vue",
  components: {TeamStatistics, UserPanel},
  data() {
    return {
      headerShow: false,
      leagues: [],
      teams: [],
    }
  },
  props: {
    selectedLeague: null,
    selectedTeam: null
  },
  mounted() {
    this.headerShow = true;

    const options = {
      method: 'GET',
      url: 'https://api-football-v1.p.rapidapi.com/v3/leagues',
      params: {season: '2022'},
      headers: {
        'X-RapidAPI-Key': 'XXXXXXXXXX',
        'X-RapidAPI-Host': 'XXXXXXXXXXXXX'
      }
    };

    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}`
        })
      }
    }).catch(function (error) {
      console.error(error);
    });
    console.log(this.leagues)
  },
  methods: {
    dropdownShouldOpen(VueSelect) {
      if (this.league !== null) {
        return VueSelect.open
      }

      return VueSelect.search.length !== 0 && VueSelect.open
    },
    isLeagueSelected(VueSelect) {
      if (this.selectedLeague !== null) {
        return VueSelect.open
      }

      return VueSelect.search.length !== 0 && VueSelect.open
    },
  },
  watch: {
    selectedLeague: function (value) {
      console.log(this.selectedTeam)
      if (this.selectedTeam) {
        this.selectedTeam.teamName = '';
      }
      this.teams.length = 0;

      const options = {
        method: 'GET',
        url: 'https://api-football-v1.p.rapidapi.com/v3/teams',
        params: {league: value.id, season: '2022'},
        headers: {
          'X-RapidAPI-Key': 'XXXXXXXXXXXXXXXXX',
          'X-RapidAPI-Host': 'api-football-v1.p.rapidapi.com'
        }
      };

      axios.request(options).then(response => {
        for (let i = 0; i < response.data.response.length; i++) {
          this.teams.push({
            teamId: response.data.response[i].team.id.toString(),
            teamName: response.data.response[i].team.name
          })
        }
      }).catch(function (error) {
        console.error(error);
      });
    },
    selectedTeam: function (value) {
      console.log(value)
    }
  },
}
</script>

<style>
.bounce-enter-active {
  animation: bounce-in 0.5s;
}

.bounce-leave-active {
  animation: bounce-in 0.5s reverse;
}

@keyframes bounce-in {
  0% {
    transform: scale(0);
  }
  100% {
    transform: scale(1);
  }
}

.label {
  color: var(--primary);
}

.selector {
  --vs-controls-color: var(--dark);
  --vs-border-color: var(--dark);

  --vs-dropdown-bg: #282c34;
  --vs-dropdown-color: #cc99cd;
  --vs-dropdown-option-color: var(--primary);

  --vs-selected-bg: var(--primary);
  --vs-selected-color: var(--primary);

  --vs-search-input-color: var(--primary);
  --vs-dropdown-option--active-bg: var(--dark);
  --vs-dropdown-option--active-color: #eeeeee;

  --vs-border-radius: 20px;

  --vs-search-input-bg: rgb(185, 73, 73);
  --vs-search-input-placeholder-color: inherit;
}
</style>

小组统计.vue(子系):

<template>
  <div class="popup">
    <div class="popup-inner">
      <h2> {{ this.teamStatistics[0].name }} </h2>
      <img :src="this.teamStatistics[0].photo" alt="teamStatistics photo" style="width: 30%; border-radius: 20px;">
      <div>Form: {{ this.teamStatistics[0].form }}</div>

      <div>
        <div>Played: {{ this.teamStatistics[0].played }}</div>
        <div>wins: {{ this.teamStatistics[0].wins }}</div>
        <div>draws: {{ this.teamStatistics[0].draws }}</div>
        <div>loses: {{ this.teamStatistics[0].loses }}</div>
        <div>Goals scored: {{ this.teamStatistics[0].goalsFor }}</div>
        <div>Goals against: {{ this.teamStatistics[0].goalsAgainst }}</div>
        <div>Biggest win streak: {{ this.teamStatistics[0].biggestWinStreak }}</div>
        <div>Biggest wins: {{ this.teamStatistics[0].biggestWins }}</div>
      </div>
    </div>
  </div>
</template>

<script>
import axios from "axios";

export default {
  name: "TeamStatistics.vue",
  props: {
    data: {
      selectedLeague: String,
      selectedTeam: String
    }
  },
  data() {
    return {
      teamStatistics: []
    }
  },
  mounted() {
    document.getElementsByClassName('popup')[0].style.visibility = 'hidden';

    setTimeout(function () {
      document.getElementsByClassName('popup')[0].style.visibility = 'visible';
    }, 600);

    this.teamStatistics.length = 0;

    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 => {
        this.teamStatistics.push({
          name: response.data.response.team.name,
          photo: response.data.response.team.logo,
          form: response.data.response.form,
          played: response.data.response.fixtures.played.total,
          wins: response.data.response.fixtures.wins.total,
          draws: response.data.response.fixtures.draws.total,
          loses: response.data.response.fixtures.loses.total,
          goalsFor: response.data.response.goals.for.total.total,
          goalsAgainst: response.data.response.goals.against.total.total,
          biggestWinStreak: response.data.response.biggest.streak.wins,
          biggestWins: response.data.response.biggest.wins,
        })
      })
      this.teamStatistics.forEach(function (o) {
        Object.keys(o).forEach(function (k) {
          if (o[k] === null) {
            o[k] = 'No info';
          }
        })
      })
      console.log(this.teamStatistics)

  }
}
</script>

<style scoped>

.team-details {
  margin-top: 10px;
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  grid-template-rows: 1fr 1fr 1fr 1fr 1fr;
  grid-auto-columns: 1fr 1fr;
  gap: 1em 1em;
  grid-auto-flow: row;
}

</style>

响应示例:

let response = {
      "league": {
        "id": 39,
        "name": "Premier League",
        "country": "England",
        "logo": "https://media.api-sports.io/football/leagues/39.png",
        "flag": "https://media.api-sports.io/flags/gb.svg",
        "season": 2022
      },
      "team": {
        "id": 33,
        "name": "Manchester United",
        "logo": "https://media.api-sports.io/football/teams/33.png"
      },
      "form": "LLWWWWLWDWDWLW",
      "fixtures": {
        "played": {
          "home": 6,
          "away": 8,
          "total": 14
        },
        "wins": {
          "home": 4,
          "away": 4,
          "total": 8
        },
        "draws": {
          "home": 1,
          "away": 1,
          "total": 2
        },
        "loses": {
          "home": 1,
          "away": 3,
          "total": 4
        }
      },
      "goals": {
        "for": {
          "total": {
            "home": 9,
            "away": 11,
            "total": 20
          },
          "average": {
            "home": "1.5",
            "away": "1.4",
            "total": "1.4"
          },
          "minute": {
            "0-15": {
carvr3hs

carvr3hs1#

首先,删除模板中的每个this
如何将多个prop值传递到组件中?
假设您希望动态地执行此操作,则可以使用v-bind,如下所示:
第一个
在这种情况下,componentProps可以是一个函数,也可以是计算的,其中返回对象的键是属性。
另外,document.getElementsByClassName('popup')[0].style.visibility = 'hidden';不要这样做。使用v-show和一个变量。(docs)
在您的TeamStatistics中,您拥有:

props: {
    data: {
      selectedLeague: String,
      selectedTeam: String
    }
  },

并且您正在将v-model与其他道具一起使用:selectedLeagueselectedTeam。将TeamStatistics.vue中的props定义更改为如下所示:

props: ['selectedLeague', 'selectedTeam']

(道具文档)
如果你想要双向数据绑定(v-model就是用来绑定的),那么你必须从你的TeamStatistics.vue发出一个事件,比如:

$emit('update:selectedLeague',"some-value-here");
$emit('update:selectedTeam',"some-other-value-here");

查看此以了解更多详细信息。

相关问题