Je souhaite obtenir des informations sur une formation complète concernant le thème DIVI dispensé
par un organisme de formation certifié par l’état.
Que la formation soit finançable par mon CPF (idéalement) ou autre


Dans la plupart des cas, lors de la création de votre application JavaScript, vous souhaiterez obtenir ou utiliser des données à partir d’une source distante API. Il y a beaucoup de choses intéressantes qui peuvent être faites avec les données d’une gamme de API accessibles au public.

Avec Vue.jsVous pouvez littéralement créer une application autour de l’un de ces services et commencer à diffuser du contenu aux utilisateurs en quelques minutes.

Je vais montrer comment créer une application d’actualités simple qui affiche les meilleurs articles d’actualité du jour et permet aux utilisateurs de filtrer et d’extraire des données en fonction de leur catégorie d’intérêt l’API du New York Times. Vous pouvez trouver le code complet de ce tutoriel Iciet une démo en direct de l’application terminée Ici.

Voici à quoi ressemble l’application finale:

vue-news-final-app

Pour pouvoir suivre ce tutoriel, vous avez besoin de Node.js et (facultatif) fil installé sur votre ordinateur. Pour installer Node, vous pouvez soit aller à page de téléchargement officielle et accédez aux binaires des nœuds de votre système ou utilisez un Gestionnaire de version au lieu.

Après avoir installé Node, procédez comme suit pour insérer la ficelle:

npm i -g yarn

Vous avez également besoin d’une connaissance de base de Vue.js. Voici un excellent guide pour vous aider à démarrer Ici.

Obtenir une clé API

Pour pouvoir utiliser l’API NYTimes, vous avez besoin d’une clé API. Alors si tu n’en as pas, vas-y Page de connexion et inscrivez-vous pour obtenir une clé API pour cela API Top Stories.

01-nyt-register-api-key

Nous utiliserons cela Meilleures histoires Point de terminaison de l’API à partir duquel obtenir des données. Notez que cette API comporte plusieurs sections telles que Accueil, Voyage, Art et Science. Nous devons créer un filtre qui permettra aux utilisateurs de sélectionner une section et d’y charger les histoires.

Voici des exemples d’appels:

//api.nytimes.com/svc/topstories/v2/arts.json?api-key=yourkey
//api.nytimes.com/svc/topstories/v2/home.json?api-key=yourkey
//api.nytimes.com/svc/topstories/v2/science.json?api-key=yourkey
//api.nytimes.com/svc/topstories/v2/us.json?api-key=yourkey
//api.nytimes.com/svc/topstories/v2/world.json?api-key=yourkey

N’hésitez pas à utiliser votre client REST préféré (ex Hoppscotch ou insomnie) pour tester vos appels API.

Client de repos insomnie

Structure du projet

Commençons rapidement avec un projet Vue 3 Vite, un serveur développeur plus rapide que Vue CLI::

yarn create @vitejs/app vue-news-app --template vue


cd vue-news-app
yarn install


yarn dev

ouvrir localhost:3000 dans votre navigateur. Vous devriez avoir la vue suivante:

Créer une application Vue

Ensuite, nous installons le Vent arrière CSS Cadre pour le style de base. Vous devez arrêter le serveur pour effectuer cette action:

yarn add -D [email protected] [email protected] [email protected]


npx tailwindcss init -p

Nous avons besoin de quelques utilitaires de package supplémentaires pour formater les dates et le nombre de lignes pour la pince abstract Champ:

yarn add @tailwindcss/line-clamp date-fns

@tailwindcss/line-clamp est un plugin qui doit être inclus tailwind.config.js. Voici la configuration complète:

module.exports = {
  purge: ["./index.html", "./src/**/*.{vue,js,ts,jsx,tsx}"],
  darkMode: false, 
  theme: {
    extend: {},
  },
  variants: {
    extend: {},
  },
  plugins: [require("@tailwindcss/line-clamp")],
}

Ensuite, créez-en un index.css Fichier dans le src Dossier et ajoutez ce code:

@tailwind base;
@tailwind components;
@tailwind utilities;

body {
  @apply antialiased text-green-900 bg-green-50;
  font-family: "Gill Sans", "Gill Sans MT", Calibri, "Trebuchet MS", sans-serif;
}

#app {
  @apply flex flex-col min-h-screen overflow-x-hidden;
}

En plus d’importer les classes CSS Tailwind requises, nous avons ajouté quelques paramètres CSS que nous pouvons utiliser pour définir le thème par défaut de notre application. Nous avons également mis en place un système de mise en page flexible qui nous aidera à créer un en-tête et un pied de page collants pour notre application.

Nous devons importer index.css dans le src/main.js::

import { createApp } from "vue"
import App from "./App.vue"
import "./index.css"

createApp(App).mount("#app")

Définissons maintenant la mise en page de notre application. Supprimez d’abord tous les composants existants dans src/components. Ensuite, créez les trois fichiers suivants dans le même dossier:

  • Layout.vue
  • Header.vue
  • Footer.vue

Copiez le code suivant pour chaque fichier:

src / components / Footer.vue::

<template>
  <footer
    class="px-4 py-8 text-sm font-bold text-center text-green-100 bg-green-900">
    <p class="text-sm tracking-wide">Copyright (c) 2021 SitePoint</p>
  </footer>
</template>

src / components / Header.vue::

<template>
  <header class="flex justify-center py-6 bg-green-900 place-items-center">
    <img alt="Vue logo" src="../assets/logo.png" width="32" />
    <span class="ml-4 text-lg font-bold text-green-100 md:text-xl">
      Vue News | NYTimes Edition
    </span>
  </header>
</template>

src / components / Layout.vue::

<template>
  <Header />
  <main class="container flex-grow px-4 mx-auto my-12">
    <slot />
  </main>
  <Footer />
</template>

<script>
import Header from "./Header.vue"
import Footer from "./Footer.vue"

export default {
  components: {
    Header,
    Footer,
  },
}
</script>

Enfin mettre à jour src/App.vue::

<template>
  <Layout>
    <p>Main content goes here</p>
  </Layout>
</template>

<script>
import Layout from "./components/Layout.vue"

export default {
  components: {
    Layout,
  },
}
</script>

Courir yarn dev. Le navigateur doit se mettre à jour automatiquement.

Vue de mise en page

Une fois la mise en page de l’application terminée, nous pouvons maintenant commencer à créer la logique de base de notre application de messagerie.

Création de composants d’application d’actualités

Notre structure d’application se compose de trois nouveaux composants et d’un conteneur. src/App.vue. Le conteneur est responsable de la récupération des données postales et du remplissage des composants.

Nous devons d’abord concevoir la mise en page et rechercher ces composants. Par conséquent, nous avons d’abord besoin de données factices. Créer le fichier src/posts.json et remplissez-le avec les données suivantes:

{
  "posts": [
    {
      "title": "Stay Healthy When Exercising Outdoors",
      "abstract": "Cold weather workouts do bring unique risks, but a little planning and preparation can help whether you’re going for a winter walk, trekking in snowshoes or sledding with the kids.",
      "url": "https://www.nytimes.com/2021/02/06/at-home/exercise-outdoors-cold-weather.html",
      "byline": "By Kelly DiNardo",
      "published_date": "2021-02-06T23:40:05-05:00",
      "thumbnail": "https://static01.nyt.com/images/2021/02/07/multimedia/07ah-OUTDOOREXERCISE/07ah-OUTDOOREXERCISE-mediumThreeByTwo210.jpg",
      "caption": ""
    },
    {
      "title": "4 Skiers Killed in Avalanche in Utah, Officials Say",
      "abstract": "It was the third such deadly episode in days and the deadliest avalanche in the United States since May 2014, according to the authorities.",
      "url": "https://www.nytimes.com/2021/02/06/us/avalanche-salt-lake-city.html",
      "byline": "By Michael Levenson",
      "published_date": "2021-02-06T20:22:39-05:00",
      "thumbnail": "https://static01.nyt.com/images/2021/02/06/lens/06xp-avalanche-photo2/06xp-avalanche-photo2-mediumThreeByTwo210.jpg",
      "caption": "A helicopter returning to Millcreek Canyon after rescuing one of the four avalanche survivors on Saturday."
    }
  ]
}

Je vous encourage à dupliquer les ensembles de données pour mieux tester nos dispositions de conception de composants, mais je ne vais pas le faire ici pour des raisons d’espace.

Commençons maintenant à créer nos composants d’actualités. En faisant src/components Dossier, créez les fichiers suivants:

  • NewsCard.vue
  • NewsList.vue
  • NewsFilter.vue

Pour visualiser comment tous ces composants sont réunis, importez-les dans src/App.vue et configurez-les comme suit:

<template>
  <Layout>
    <h2 class="mb-8 text-4xl font-bold text-center capitalize">
      News Section : <span class="text-green-700">{{ section }}</span>
    </h2>
    <NewsFilter v-model="section" />
    <NewsList :posts="posts" />
  </Layout>
</template>

<script>
import Layout from "./components/Layout.vue"
import NewsFilter from "./components/NewsFilter.vue"
import NewsList from "./components/NewsList.vue"

import data from "./posts.json"

export default {
  components: {
    Layout,
    NewsFilter,
    NewsList,
  },
  data() {
    return {
      section: "home",
      posts: data.posts,
    }
  },
}
</script>

Décomposons le code ci-dessus:

  • le header Le jour est l’endroit où nous afficherons la valeur de statut actuelle de section.
  • le NewsFilter Le composant comprend une entrée déroulante qui permet aux utilisateurs de sélectionner une section différente. Il y aura un bouton sur lequel vous devrez cliquer pour effectuer la récupération. Nous avons lié le composant à l’État section pour activer la synchronisation des états.
  • le NewsList Le composant affiche les articles avec le NewsCard Composant via une grille attractive.

Commençons maintenant à travailler avec chaque composant d’actualités. le NewsCard.vue Le composant affiche les données d’un seul article. Cela nécessite un accessoire post::

<template>
  <section class="p-4 rounded-lg shadow-lg bg-gray-50 w-80">
    <div class="h-96">
      <a
        class="text-xl font-bold text-center text-green-800 hover:text-green-600 hover:underline"
        :href="post.url"
        target="_blank"
        rel="noreferrer"
      >
        {{ post.title }}
      </a>
      <img
        class="w-full mt-2 rounded"
        :src="post.thumbnail"
        :alt="post.caption"
        height="140"
        width="210"
      />
      <p class="mt-2 text-justify text-gray-700 line-clamp-4">
        {{ post.abstract }}
      </p>
    </div>
    <div>
      <p class="mt-4 font-bold text-gray-600">{{ post.byline }}</p>
      <p class="font-light text-gray-600">
        {{ formatDate(post.published_date) }}
      </p>
    </div>
  </section>
</template>

<script>
import { format } from "date-fns"

export default {
  props: {
    post: {
      type: Object,
      required: true,
    },
  },
  methods: {
    formatDate(strDate) {
      return format(new Date(strDate), "MMMM do, yyyy")
    },
  },
}
</script>

le NewsList.vue parcourt un tableau d’articles et le remplit NewsCards via une grille réactive:

<template>
  <div
    class="grid grid-cols-1 gap-6 mt-4 md:grid-cols-2 lg:grid-cols-3 2xl:grid-cols-4 justify-items-center"
  >
    <NewsCard v-for="(post, index) in posts" :key="index" :post="post" />
  </div>
</template>

<script>
import NewsCard from "./NewsCard.vue"
export default {
  props: {
    posts: {
      type: Array,
      required: true,
    },
  },
  components: {
    NewsCard,
  },
}
</script>

Ensuite, nous avons ceux NewsFilter Composant qui permet aux utilisateurs de charger des articles à partir de différentes sections. Tout d’abord, nous avons besoin d’un fichier de contenu pour stocker toutes les sections prises en charge par le point de terminaison de l’API Top Stories. Créer le fichier src/components/sections.js::

const sections = [
  "home",
  "arts",
  "automobiles",
  "books",
  "business",
  "fashion",
  "food",
  "health",
  "insider",
  "magazine",
  "movies",
  "nyregion",
  "obituaries",
  "opinion",
  "politics",
  "realestate",
  "science",
  "sports",
  "sundayreview",
  "technology",
  "theater",
  "magazine",
  "travel",
  "upshot",
  "us",
  "world",
]

export default sections

Maintenant créons le nôtre NewsFilter.vuequi contient une entrée de sélection déroulante et un bouton. Nous devons utiliser v-model lier l’État section d’une manière qui se synchronise avec l’état dans App.vue::

<template>
  <div class="flex justify-center p-4 rounded">
    <!-- Start of select dropdown -->
    <div class="relative inline-flex">
      <svg
        class="absolute top-0 right-0 w-2 h-2 m-4 pointer-events-none"
        xmlns="http://www.w3.org/2000/svg"
        viewBox="0 0 412 232"
      >
        <path
          d="M206 171.144L42.678 7.822c-9.763-9.763-25.592-9.763-35.355 0-9.763 9.764-9.763 25.592 0 35.355l181 181c4.88 4.882 11.279 7.323 17.677 7.323s12.796-2.441 17.678-7.322l181-181c9.763-9.764 9.763-25.592 0-35.355-9.763-9.763-25.592-9.763-35.355 0L206 171.144z"
          fill="#648299"
          fill-rule="nonzero"
        />
      </svg>
      <select
        class="h-10 pl-5 pr-10 text-gray-600 bg-white border border-gray-300 rounded-lg appearance-none hover:border-gray-400 focus:outline-none"
        v-model="section"
      >
        <option
          v-for="(section, index) in sections"
          :key="index"
          :value="section"
        >
          {{ capitalize(section) }}
        </option>
      </select>
    </div>
    <!-- End of select dropdown -->
    <div class="self-center ml-8">
      <button
        class="px-6 py-2 text-white bg-green-700 rounded hover:bg-green-900"
      >
        Retrieve
      </button>
    </div>
  </div>
</template>

<script>
import { computed } from "vue"
import sectionsData from "./sections"

export default {
  props: {
    modelValue: String,
  },
  setup(props, { emit }) {
    const section = computed({
      get: () => props.modelValue,
      set: value => emit("update:modelValue", value),
    })

    return {
      section,
    }
  },
  data() {
    return {
      sections: sectionsData,
    }
  },
  methods: {
    capitalize(value) {
      if (!value) return ""
      value = value.toString()
      return value.charAt(0).toUpperCase() + value.slice(1)
    },
  },
}
</script>

L’article « Vue 3: données vers le bas, événements vers le haut«Best explique la stratégie que nous utilisons pour lier section Condition à la NewsFilter Composant. En principe, les composants subordonnés peuvent mettre à jour les accessoires et les synchroniser avec le composant de niveau supérieur.

Voici une capture d’écran de l’état actuel de l’application:

Composants du message

Utilisation d’Axios pour récupérer des données distantes

Axios est un client HTTP basé sur la promesse pour les requêtes Ajax et est idéal pour nos besoins. Il propose une API simple et complète. C’est assez similaire à ça fetch APImais sans ajouter de remplissage poly pour les navigateurs plus anciens et autres Subtilités.

Procédez comme suit pour installer Axios:

yarn add axios

Le développement de l’interface utilisateur de notre application est terminé. Il ne nous reste plus qu’à implémenter la logique d’interrogation à distance. Vous trouverez ci-dessous un exemple du format d’URL complet attendu par le service API NYTimes:

//api.nytimes.com/svc/topstories/v2/home.json?api-key=your_api_key

Commençons par enregistrer notre clé API dans un .env Fichier dans le répertoire racine de notre projet. Enregistrez au format suivant:

VITE_NYT_API_KEY=####

Remplacez les hachages par votre clé API réelle.

Puisque nous utilisons Vite, nous devons adhérer à Vite’s Manuel lors du chargement des variables d’environnement. Vue / CLI a son propre Manuel pour faire de même.

Maintenant, implémentons la logique d’obtention de publications réelles à partir du point de terminaison de l’API REST NYTimes. Juste mettre à jour src/App.vue correspondant:

<template>
  <Layout>
    <h2 class="mb-8 text-4xl font-bold text-center capitalize">
      News Section : <span class="text-green-700">{{ section }}</span>
    </h2>
    <NewsFilter v-model="section" :fetch="fetchNews" />
    <NewsList :posts="posts" />
  </Layout>
</template>

<script>
import Layout from "./components/Layout.vue"
import NewsFilter from "./components/NewsFilter.vue"
import NewsList from "./components/NewsList.vue"

import axios from "axios"
const api = import.meta.env.VITE_NYT_API_KEY

export default {
  components: {
    Layout,
    NewsFilter,
    NewsList,
  },
  data() {
    return {
      section: "home",
      posts: [],
    }
  },
  methods: {
    
    extractImage(post) {
      const defaultImg = {
        url: "http://placehold.it/210x140?text=N/A",
        caption: post.title,
      }
      if (!post.multimedia) {
        return defaultImg
      }
      let imgObj = post.multimedia.find(
        media => media.format === "mediumThreeByTwo210"
      )
      return imgObj ? imgObj : defaultImg
    },
    async fetchNews() {
      try {
        const url = `https://api.nytimes.com/svc/topstories/v2/${this.section}.json?api-key=${api}`
        const response = await axios.get(url)
        const results = response.data.results
        this.posts = results.map(post => ({
          title: post.title,
          abstract: post.abstract,
          url: post.url,
          thumbnail: this.extractImage(post).url,
          caption: this.extractImage(post).caption,
          byline: post.byline,
          published_date: post.published_date,
        }))
      } catch (err) {
        if (err.response) {
          
          console.log("Server Error:", err)
        } else if (err.request) {
          
          console.log("Network Error:", err)
        } else {
          console.log("Client Error:", err)
        }
      }
    },
  },
  mounted() {
    this.fetchNews()
  },
}
</script>

Ici, nous avons appelé une fonction appelée fetchNews il contient une logique pour exécuter la logique de récupération. Cette fonction est appelée à partir de deux endroits:

  • le mounted() Événement du cycle de vie
  • le NewsFilter composant

Décomposons la fonctionnalité pour nous assurer que nous comprenons ce qui se passe:

  • Nous utilisons syntaxe asynchroneparce qu’il est plus propre que d’habitude Promise Syntaxe de rappel.
  • Puisque nous sommes sur le point de passer un appel réseau, de nombreuses choses peuvent mal tourner. Nous avons inclus le code de fonction dans un try...catch Bloquer. Sinon, les utilisateurs verront une erreur de promesse non descriptive le cas échéant.
  • Utilisant Littéraux de modèle ES6nous pouvons créer une chaîne d’url qui sera automatiquement mise à jour lorsque l’utilisateur modifie les messages section à propos de NewsFilter Composant. Notez que la clé API est également incluse dans la chaîne URL.
  • Après avoir obtenu les résultats avec le axios.get() Fonction, nous devons analyser les résultats et les formater afin qu’ils soient compatibles avec notre interface utilisateur, en particulier le NewsCard Composant. Nous faisons cela avec JavaScript Array.map Fonction pour créer un nouveau tableau avec nos données formatées.
  • L’extraction des données d’image est un peu difficile. Cela manque dans certains articles multimedia Field, et même s’ils le font, il n’y a aucune garantie que ce sera le format de média dont nous avons besoin. Dans ce cas, nous retournerons une URL d’image standard – http://placehold.it/210x140?text=N/A – et utilisez le titre du message comme légende.
  • Dans le bloc d’erreur, nous vérifions la présence de certaines propriétés d’erreur pour déterminer quel type d’erreur s’est produit. Vous pouvez utiliser ces informations pour créer un message d’erreur utile.

Jetez maintenant un œil à la section des modèles et notez que nous avons ajouté un nouvel accessoire appelé fetchqui fait référence au fetchNews Une fonction. Nous devons mettre à jour src/components/NewsFilter.vue d’accepter cet accessoire. Ci-dessous, je viens de mettre en évidence les sections de code que vous devez modifier:

<template>
  ...
  <button
    class="px-6 py-2 text-white bg-green-700 rounded hover:bg-green-900"
    @click="fetch"
  >
    Retrieve
  </button>
  ...
</template>

<script>
export default {
  props: {
    modelValue: String,
    fetch: Function,
  },
}
</script>

Vous devrez probablement redémarrer le serveur de développement pour que la bibliothèque Axios et la clé API se chargent correctement. Une fois que vous avez fait cela, vous devriez avoir un aperçu des publications réelles. Vous trouverez ci-dessous l’état actuel de l’application.

Obtenez Axios

Vous devriez pouvoir basculer et charger différentes zones de message.

Dernières touches et démos

J’ai décidé d’ajouter quelques touches mineures (facultatives) pour améliorer un peu l’application, comme l’introduction d’une image de chargement.

Vous pouvez voir une démo dans le StackBlitz ci-dessous (fonctionnalités limitées):

Vous pouvez également afficher une version en direct Ici.

Conclusion

Dans ce tutoriel, nous avons appris comment démarrer un projet Vue.js à partir de zéro et comment obtenir des données à partir d’une API avec Axioset comment gérer les réponses et manipuler les données à l’aide de composants et de propriétés calculées.

Nous avons maintenant une application Vue.js 3.0 fonctionnelle basée sur un service API. De nombreuses améliorations pourraient être apportées en branchant quelques autres API. Par exemple, nous pourrions:

  • Met automatiquement en file d’attente les publications sur les réseaux sociaux d’une catégorie API de tampon
  • Marquez les articles qui devraient être lus plus tard avec le API de poche

… etc.

Tout le code de ce projet est également hébergé sur GitHubC’est ainsi que vous pouvez cloner, exécuter et apporter les améliorations que vous souhaitez.



Source link

Recent Posts