简体   繁体   English

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

[英]Multiply v-model props to Vue 3 component to fetch API breakpoint

I am trying to fetch API breakpoint in my child component .我正在尝试在我的子组件中获取 API 断点
Components are made for my football web app.组件是为我的足球 web 应用程序制作的。
Breakpoints from: api-football断点来自: api-football

How can I pass multiple prop values into component?如何将多个 prop 值传递到组件中?
In debugging only the second prop is being read in parent component (in this case (league)).在调试中,只有第二个道具被父组件读取(在本例中为(联盟))。

Errors:错误:

  1. https://api-football-v1.p.rapidapi.com/v3/teams?league=39&season=2022 https://api-football-v1.p.rapidapi.com/v3/teams?league=39&season=2022

If you have additional time you can comment some code review about it.如果你有额外的时间,你可以评论一些关于它的代码审查。 I am learning Vue.我正在学习 Vue。

Teams.vue (parent): Teams.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>

TeamStatistics.vue (child): TeamStatistics.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>

Example response:示例响应:

    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": {

First, remove every this in your templates.首先,删除模板中的所有this

How can I pass multiple prop values into a component?如何将多个 prop 值传递到一个组件中?

Assuming you want to do it dynamically, you can use v-bind , like this:假设您想动态地执行此操作,您可以使用v-bind ,如下所示:

<MyComponent v-bind="componentProps"/>
componentProps() {
    return {
        propA:'foo',
        propB: 'bar'
        ...
    }
}

In this case, componentProps can be a function or computed where the return object's keys are the props.在这种情况下, componentProps可以是 function 或计算,其中返回对象的键是道具。

Also, document.getElementsByClassName('popup')[0].style.visibility = 'hidden';此外, document.getElementsByClassName('popup')[0].style.visibility = 'hidden'; Do not do that.不要那样做。 Use v-show with a variable instead.请改用带变量的v-show ( docs ) 文档

In your TeamStatistics you have:在您的TeamStatistics ,您有:

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

and you are using v-model with other props: selectedLeague and selectedTeam .并且您将 v-model 与其他道具一起使用: selectedLeagueselectedTeam Change the props definition in your TeamStatistics.vue to something like:TeamStatistics.vue中的道具定义更改为:

props: ['selectedLeague', 'selectedTeam']

(props docs ) 道具文档

Then you should be able to use v-model:selectedLeague properly.然后你应该能够正确使用v-model:selectedLeague If you want the two-way data binding (which v-model is used for), then you have to emit an event from your TeamStatistics.vue like:如果你想要双向数据绑定(v-model 用于),那么你必须从你的TeamStatistics.vue发出一个事件,如:

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

Check this for more details.检查以获取更多详细信息。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM