Pour chaque photo on aura donc une liste d'avis et un formulaire pour déposer le sien.

Surprise surprise ;)
Récupération des photos
La NASA met à disposition une API qui permet de récupérer ces photos. Il y a plein d'API super intéressantes. Je te propose ici deux API disponibles à utiliser. Une qui permet de récupérer les photos prises par des rovers sur Mars, l'autre qui permet de récupérer les "photos du jour" prises par des télescopes, des amateurs, etc. Durant tout le tutoriel j'utiliserai la clé d'API (c'est à dire la clé qui permet de se connecter à l'API) de démo. On est limité à 50 appels d'API par IP par jour. Si tu en veux plus, tu peux te créer un compte. Voici le lien pour avoir la documentation et toutes les informations utiles : https://api.nasa.gov.
Petite anecdote : j'aurais bien aimé utiliser des photos proposées par ArianeSpace ou l'Agence Spatiale Européenne, malheureusement il n'y a pas, à ma connaissance, d'API simple d'utilisation pour récupérer ces données.
Code type pour utilisation de l'API concernant les rovers
Voici le code type que tu pourras utiliser si tu souhaites utiliser les photos de Curiosity qui patrouille sur Mars.
{"language":"text/html","content":"<template>\n <figure v-for=\"photo in photos\" :key=\"photo.id\">\n <img :src=\"photo.img_src\" />\n </figure>\n</template>\n\n<script>\nconst API_URL = 'https://api.nasa.gov/mars-photos/api/v1/rovers/curiosity/photos?&page=1&sol=1000&api_key=DEMO_KEY'\nexport default {\n name: 'App',\n data() {\n return {\n photos: []\n }\n },\n created() {\n fetch(API_URL)\n .then(result => result.json())\n .then(result => {this.photos = result.photos})\n }\n}\n</script>","filename":"App.vue"}
Code type pour utilisation de l'API concernant les "photos of the day"
Et voici donc le deuxième code type :
{"language":"text/html","content":"<template>\n <figure v-for=\"photo in photos\" :key=\"photo\">\n <img :src=\"photo.url\" :alt=\"photo.title + 'prise par' +photo.copyright\" />\n <figcaption>\n <h2>{{ photo.title }} prise le {{ photo.date }}</h2>\n <p>{{ photo.explanation }}</p>\n </figcaption>\n </figure>\n</template>\n\n<script>\nconst API_URL = 'https://api.nasa.gov/planetary/apod?start_date=2021-02-01&end_date=2021-02-17&api_key=DEMO_KEY'\nexport default {\n name: 'App',\n data() {\n return {\n photos: []\n }\n },\n created() {\n fetch(API_URL)\n .then(result => result.json())\n .then(result => {this.photos = result})\n }\n}\n</script>\n","filename":"App.vue"}
Pour ma part durant ce cours je vais utiliser ce deuxième code. Il me semble plus intéressant (et les photos sont plus diversifiées :p).

Si, et je trouvais intéressant de les utiliser justement. Ça change un peu des photos banales de service de fake API !

En fait si on regarde le résultat de notre API, les photos n'ont pas d'id ! Du coup pour identifier la photo dans la boucle, je mets directement l'objet entier de :key. C'est quelque chose qui est licite, on retrouve parfois cette façon de faire dans la documentation de Vue.JS. On aurait pu également faire v-for="(photo, key) in photos" comme d'habitude et faire :key="key" évidemment.

Il faudra faire quelques adaptations, mais rien de bien grave. Ce sera d'ailleurs un très bon exercice pour vérifier si tu as compris le cours de le reprendre avec une autre API de la NASA (donc mon premier code par exemple). Cela te permettra également de laisser libre cours à ton imagination pour les fonctionnalités, les composants...

Excellente question. Excellente question qu'il faut se poser dès maintenant !
Le choix de nos composants
Déjà, il faut bien comprendre que lorsque je parle de composants, je parle maintenant de SFC. On n'utilisera que cette "syntaxe" pour les composants.
Maintenant se pose la question : quels composants ? Comment fais-je pour savoir ce que je peux déléguer à des composants ?
Tu as une idée ?

Oui en effet. Nous avons un composant simple à deviner dans notre cas : le composant "Photo". Et ce pour des raisons pratiques au delà de raisons de réutilisation. Imaginons qu'on veuille modifier la date de la photo pour qu'elle ait un format français. On utilisera une computed property (CP). Et une CP s'utilise sur un élément en particulier, pas sur un array. J'entends par là qu'à l'heure actuelle, on ne peut pas faire ça :
{"language":"text/html","content":"<h2>{{ photo.title }} prise le {{ dateFormatted }}</h2>","filename":"App.vue"}
Puisqu'on ne peut pas créer une CP pour une liste. On peut à la limite faire la chose suivante :
{"language":"text/html","content":"<template>\n <figure v-for=\"photo in photos\" :key=\"photo\">\n <img :src=\"photo.url\" :alt=\"photo.title + 'prise par' +photo.copyright\" />\n <figcaption>\n <h2>{{ photo.title }} prise le {{ formattedDate(photo) }}</h2>\n <p>{{ photo.explanation }}</p>\n </figcaption>\n </figure>\n</template>\n\n<script>\nconst API_URL = 'https://api.nasa.gov/planetary/apod?start_date=2021-02-01&end_date=2021-02-17&api_key=DEMO_KEY'\nexport default {\n name: 'App',\n data() {\n return {\n photos: []\n }\n },\n created() {\n fetch(API_URL)\n .then(result => result.json())\n .then(result => {this.photos = result})\n },\n methods: {\n formattedDate(photo) {\n let date = new Date(photo.date)\n let day = Number(date.getDate()) >= 10 ? date.getDate() : '0'+date.getDate()\n return `${day}/${date.getMonth()}/${date.getFullYear()}`\n }\n }\n}\n</script>","filename":"App.vue"}
Mais c'est moins propre. Il est donc évident qu'on utilisera un composant pour nos photos. La logique est la même pour le formulaire des avis pour chaque photo : on mettrait un v-model comment ? Si on utilise le code ci-dessous, on aura le même avis qui sera rempli pour toutes les photos...
{"language":"text/html","content":"<figcaption>\n <h2>{{ photo.title }} prise le {{ formattedDate(photo) }}</h2>\n <p>{{ photo.explanation }}</p>\n\t<textarea v-model=\"avis\"></textarea>\n</figcaption>","filename":"App.vue"}
Tu comprends le problème ?

C'est tout à fait juste. Tu peux te demander si tu as besoin d'un composant quand tu te verras utiliser dans tes templates des choses suivantes :
{"language":"text/html","content":"<button @click=\"doSomethingOn(element)\"></button>\n<!-- ou -->\n<input v-model=\"avis[element.id]\">\n<!-- ... -->","filename":"App.vue"}
De manière plus générale (mais pas 100% vraie), dès que tu boucles sur des éléments, tu peux te demander si tu as besoin d'un composant.

Non. Il n'y a pas de science exacte du composant, mais en général ça se "sent" quand on en a besoin. On peut aussi découper toute notre application sous forme de composants pour des raisons de flexibilité, maintenabilité. Il est par exemple recommandé par TailwindCSS (http://tailwindcss.com) d'utiliser des composants pour chacun des éléments du design qui sont amenés à être réutilisés. Par exemple une navbar, des boutons, des cards...

Tout à fait.
La création de nos composants
On va donc créer notre composant Photo. Je te laisse créer un nouveau fichier Photo.vue qu'on mettra dans le dossier "components".
{"language":"text/html","content":"<template>\n <figure>\n <img :src=\"photo.url\" :alt=\"photo.title + 'prise par' +photo.copyright\" />\n <figcaption>\n <h2>{{ photo.title }} prise le {{ formattedDate }}</h2>\n <p>{{ photo.explanation }}</p>\n </figcaption>\n </figure>\n</template>\n\n<script>\n export default {\n computed: {\n formattedDate() {\n let date = new Date(photo.date)\n let day = Number(date.getDate()) >= 10 ? date.getDate() : '0'+date.getDate()\n return `${day}/${date.getMonth()}/${date.getFullYear()}`\n }\n }\n }\n</script>\n\n<style>\n\n</style>","filename":"Photo.vue"}
{"language":"text/html","content":"<template>\n <photo v-for=\"photo in photos\" :key=\"photo\"></photo>\n</template>\n\n<script>\nimport Photo from './components/Photo.vue'\nconst API_URL = 'https://api.nasa.gov/planetary/apod?start_date=2021-02-01&end_date=2021-02-17&api_key=DEMO_KEY'\nexport default {\n name: 'App',\n components: {\n Photo\n },\n\n data() {\n return {\n photos: [],\n }\n },\n created() {\n fetch(API_URL)\n .then(result => result.json())\n .then(result => {this.photos = result})\n }\n}\n</script>\n","filename":"App.vue"}

Tout à fait ! C'est comme une autre balise ;)
Par contre, si tu mets tout ça en place, tu auras l'erreur suivante :


Hé bien oui, en réalité, même si on a fait le v-for sur <photo> notre composant lui n'a pas accès à ces données.

On va devoir lui passer. Et ce grâce aux props. On voit ça justement dans le chapitre suivant ;) J'ai terminé cette partie