Je montre les paramètres de données (nom, hauteur, masse ...) d'un personnage utilisant le swapi ( https: //swapi.co/ ), AXIOS et VUE.
J'ai déjà l'URL d'un caractère (c'est-à-dire http: // localhost: 8081 / person / 1 ) et je souhaite qu'il corresponde à l'API swapi ( https://swapi.co/api/people/1/ ), mais je ne sais pas où est mon erreur
J'utilise Axios et Vue, j'ai créé un service pour la requête Axios get et la méthode pour obtenir les informations dans mon fichier vue.
Le code de mon service "people.service.js" est le suivant: p >
<template>
<div>
The id is {{ $route.params.id }}, and the name is {{ people.nombre }}
</div>
</template>
<script>
import PeopleService from "@/services/people.service";
export default {
async create() {
this.userId = this.$route.params.id;
this.getUser();
},
data() {
return {
user: null,
loading: false,
error: null,
userId: this.$route.params.id
};
},
methods: {
async getUser() {
try {
this.loading = true;
this.people = null;
this.error = null;
this.people = await PeopleService.getPeople(this.userId);
} catch (error) {
this.error = error.message;
} finally {
this.userId = null;
this.loading = false;
}
}
}
};
</script>
<style lang="scss" scoped></style>
Et mon fichier vue est:
import axios from "axios";
const PeopleService = {};
// PeoplesService.getPeoples = async () => {}; - Para sacar el listado de planetas con un v-for
PeopleService.getPeople = async id => {
try {
const result = await axios.get(`people/${id}`);
// For getting the species
const specieRoute = result.data.species[0].split("/");
const idSpecie = specieRoute[specieRoute.length - 2];
const especie = await axios.get(`species/${idSpecie}`);
// For getting the planets
const planetRoute = result.data.homeworld.split("/");
const idPlanet = planetRoute[planetRoute.length - 2];
const planeta = await axios.get(`planets/${idPlanet}`);
// console logs to show results
console.log(result.data);
console.log(idSpecie);
console.log(especie.data);
console.log(planeta.data);
// data information
const people = {
nombre: result.data.name,
altura: result.data.height,
peso: result.data.mass,
genero: result.data.gender,
piel: result.data.skin_color,
especie: especie.data.name, // Lo saco del servicio de especies
planeta: planeta.data.name // Lo saco del servicio de planetas
};
return people;
} catch (error) {
const errorStatus = error.response.status;
let errorMessage = "";
if (errorStatus === 404) {
errorMessage = "No se encontró al personaje";
} else {
errorMessage = "Ocurrió un error";
}
throw new Error(errorMessage);
}
};
export default PeopleService;
Je m'attends à ce que le résultat soit le nom du personnage, mais j'obtiens "[Vue warn]: Erreur de rendu:" TypeError: Impossible de lire la propriété 'nombre' d'undefined "
3 Réponses :
Edit: il ne semble pas que vous ayez configuré une propriété data.people avant de lui attribuer une valeur. Pouvez-vous essayer d'ajouter une propriété people sous les données et réessayer?
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.10/vue.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.18.0/axios.min.js"></script>
<div id="app">
<h3>People as ARRAY</h3>
<div v-if="peopleArray.length > 0">
<div v-for="(p, index) in peopleArray" :key="index">
<div><b>nombre:</b> {{ p.nombre }}</div>
<div><b>altura:</b> {{ p.altura }}</div>
<div><b>peso:</b> {{ p.peso }}</div>
<div><b>genero:</b> {{ p.genero }}</div>
<div><b>piel:</b> {{ p.piel }}</div>
<div><b>especie:</b> {{ p.especie }}</div>
<div><b>planeta:</b> {{ p.planeta }}</div>
</div>
</div>
<div v-else>
<i>Loading People...</i>
</div>
<br/><hr/> --- OR --- <hr/><br/>
<h3>People as OBJECT</h3>
<div v-if="peopleObject != null">
<div v-for="(p, index) in peopleObject" :key="index">
{{ p }}
</div>
</div>
<div v-else>
<i>Loading People...</i>
</div>
</div>D'abord et avant tout, la manière dont vous envoyez réellement les demandes à swapi .. comment faites-vous cela?
J'ai écrit une version modifiée de ce que vous essayez d'accomplir en utilisant votre code, mais avec l'URL swapi .. si vous modifiez votre code pour utiliser le swapi URL au lieu de localhost , ça marche?
L'extrait de code est également disponible ci-dessous
Modifier: em> CodePen avec exemple de routage - une réponse secondaire détaillée a également été publiée.
Si vous envoyez des requêtes par proxy localement
À quoi ressemble votre configuration côté serveur? Utilisez-vous node ou autre chose? Comment en fait envoyer des requêtes API à swapi?
Si vous utilisez une base de données locale
Votre base de données locale contient-elle des données? Vous devrez peut-être configurer un service qui extrait les données de l'API swapi et les enregistre dans votre base de données locale, avant d'essayer d'interroger votre base de données locale pour les données.
Je n'utilise pas non plus de routage, il pourrait donc y avoir un problème avec vos itinéraires? En tout cas, j'espère que cela aidera:
/**
* People service
*/
const PeopleService = {};
PeopleService.getPeople = async id => {
try {
const result = await axios.get(`https://swapi.co/api/people/${id}`);
const specieRoute = result.data.species[0].split("/");
const idSpecie = specieRoute[specieRoute.length - 2];
const especie = await axios.get(`https://swapi.co/api/species/${idSpecie}`);
const planetRoute = result.data.homeworld.split("/");
const idPlanet = planetRoute[planetRoute.length - 2];
const planeta = await axios.get(`https://swapi.co/api/planets/${idPlanet}`);
const people = {
nombre: result.data.name,
altura: result.data.height,
peso: result.data.mass,
genero: result.data.gender,
piel: result.data.skin_color,
especie: especie.data.name,
planeta: planeta.data.name
};
return people;
} catch (error) {
const errorStatus = error.response.status;
let errorMessage = "";
if (errorStatus === 404) {
errorMessage = "No se encontró al personaje";
} else {
errorMessage = "Ocurrió un error";
}
throw new Error(errorMessage);
}
};
/**
* Vue app
*/
new Vue({
el: "#app",
data: {
userId: 1,
peopleArray: [],
peopleObject: null,
error: null
},
mounted() {
this.getUser();
},
methods: {
async getUser() {
try {
let person = await PeopleService.getPeople(this.userId);
this.peopleArray.push(person); // add to array
this.peopleObject = person; // assign to object
} catch (error) {
this.error = error.message;
}
}
}
});
...
data() {
return {
...
people: null,
...
}
}
...
Ça marche! le problème principal est maintenant avec l'ID utilisateur, je veux qu'il corresponde à mon url, par exemple, si localhost / person / 5, j'ai besoin de l'ID utilisateur = 5. J'ai utilisé userID: this. $ Router.params.id, mais ne fait rien.
Qu'est-ce qui a fonctionné? Ajouter la propriété people sous les données? Il est difficile de dire ce qui ne va pas avec vos itinéraires sans voir une configuration de routeur. Pouvez-vous mettre à jour votre question avec la configuration de votre routeur?
Je suis en train de créer une deuxième réponse afin de décrire comment vous pourriez faire cela en utilisant vue-router , puisque vous le posiez.
Clause de non-responsabilité: ce n'est pas le code le plus "propre" - ce pseudo code est conçu pour illustrer vaguement votre objectif.
J'espère que cela vous aidera!
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.10/vue.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue-router/3.0.4/vue-router.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.18.0/axios.min.js"></script>
<div id="app">
<div>
<router-view></router-view>
</div>
</div>
<script type="text/x-template" id="homeComponent">
<div>
<hr/>
<div class="nav-links">
<h2>Home</h2>
<div>
<router-link :to="{ name: 'people', params: { id: 1 } }">Person 1</router-link>
<br/>
<router-link :to="{ name: 'people', params: { id: 2 } }">Person 2</router-link>
</div>
</div>
<hr/><br/>
</div>
</script>
<script type="text/x-template" id="peopleComponent">
<div>
<hr/>
<div class="nav-links">
<h2>People</h2>
<div>
<router-link :to="{ name: 'home' }">Home</router-link>
</div>
</div>
<hr/><br/>
<h3>People as ARRAY</h3>
<div v-if="peopleArray.length > 0">
<div v-for="(p, index) in peopleArray" :key="index">
<div><b>nombre:</b> {{ p.nombre }}</div>
<div><b>altura:</b> {{ p.altura }}</div>
<div><b>peso:</b> {{ p.peso }}</div>
<div><b>genero:</b> {{ p.genero }}</div>
<div><b>piel:</b> {{ p.piel }}</div>
<div><b>especie:</b> {{ p.especie }}</div>
<div><b>planeta:</b> {{ p.planeta }}</div>
</div>
</div>
<div v-else>
<i>Loading People...</i>
</div>
<br/>
<hr/> --- OR ---
<hr/><br/>
<h3>People as OBJECT</h3>
<div v-if="peopleObject != null">
<div v-for="(p, index) in peopleObject" :key="index">
{{ p }}
</div>
</div>
<div v-else>
<i>Loading People...</i>
</div>
</div>
</script>
.nav-links {
background-color: lightgray;
text-align: center;
}
const PeopleService = {};
PeopleService.getPeople = async id => {
try {
const result = await axios.get(`https://swapi.co/api/people/${id}`);
const specieRoute = result.data.species[0].split("/");
const idSpecie = specieRoute[specieRoute.length - 2];
const especie = await axios.get(`https://swapi.co/api/species/${idSpecie}`);
const planetRoute = result.data.homeworld.split("/");
const idPlanet = planetRoute[planetRoute.length - 2];
const planeta = await axios.get(`https://swapi.co/api/planets/${idPlanet}`);
const people = {
nombre: result.data.name,
altura: result.data.height,
peso: result.data.mass,
genero: result.data.gender,
piel: result.data.skin_color,
especie: especie.data.name, // Lo saco del servicio de especies
planeta: planeta.data.name // Lo saco del servicio de planetas
};
return people;
} catch (error) {
const errorStatus = error.response.status;
let errorMessage = "";
if (errorStatus === 404) {
errorMessage = "No se encontró al personaje";
} else {
errorMessage = "Ocurrió un error";
}
throw new Error(errorMessage);
}
};
const peopleComponent = {
name: 'people',
template: "#peopleComponent",
data() {
return {
userId: null,
peopleArray: [],
peopleObject: null,
error: null
};
},
mounted() {
this.userId = this.$route.params.id;
this.getUser();
},
methods: {
async getUser() {
try {
let person = await PeopleService.getPeople(this.userId);
this.peopleArray.push(person); // add to array
this.peopleObject = person; // assign to object
} catch (error) {
this.error = error.message;
}
}
}
};
const homeComponent = {
name: 'home',
template: "#homeComponent",
}
const routes = [
{ path: '', name: 'home', component: homeComponent },
{ path: '/people/:id', name: 'people', component: peopleComponent },
]
const router = new VueRouter({ routes });
new Vue({
router
}).$mount('#app');
Génial! c'est exactement ce que je cherchais, mon problème était avec le userId en monté!
N'hésitez pas à appuyer sur ce bouton de vote positif si cela vous a aidé;) cela m'aiderait énormément!
Le code correct pour le fichier vue est:
<template>
<div>
<h3>Modo array</h3>
<div v-if="peopleArray.length > 0"> // Detecta que el id es mayor que 0
<div v-for="(p, index) in peopleArray" :key="index">
<div><b>nombre:</b> {{ p.nombre }}</div>
<div><b>altura:</b> {{ p.altura }}</div>
<div><b>peso:</b> {{ p.peso }}</div>
<div><b>genero:</b> {{ p.genero }}</div>
<div><b>piel:</b> {{ p.piel }}</div>
<div><b>especie:</b> {{ p.especie }}</div>
<div><b>planeta:</b> {{ p.planeta }}</div>
</div>
</div>
<div v-else>
<i>Loading People...</i>
</div>
<br/><hr/> --- <hr/><br/>
<h3>Modo objeto</h3>
<div v-if="peopleObject != null">
<div v-for="(p, index) in peopleObject" :key="index">
{{ p }}
</div>
</div>
<div v-else>
<i>Loading People...</i>
</div>
</div>
</template>
<script>
import PeopleService from "@/services/people.service";
export default {
data() {
return {
userId: null,
loading: false,
peopleArray: [], // Para obtener los valores como array
peopleObject: null, // Para que los valores que devuelva sean como array o como objeto
error: null
};
},
mounted() {
this.userId = this.$route.params.id; // el userId corresponde con el último número de la url
this.getUser();
},
methods: {
async getUser() {
try {
this.loading = true;
this.people = null;
this.error = null;
let person = await PeopleService.getPeople(this.userId); // Hace la petición sobre el userID
this.peopleArray.push(person); // Añadir al array
this.peopleObject = person; // Asignar a objeto
} catch (error) {
this.error = error.message;
} finally {
this.userId = null;
this.loading = false;
}
}
}
};
</script>
<style lang="scss" scoped></style>