Fermer

juin 7, 2018

Créer une application de page unique JavaScript sans un cadre –


Les frameworks frontaux sont géniaux. Ils éliminent une grande partie de la complexité de la création d'une application monopage (SPA) et vous aident à organiser votre code de manière intelligible au fur et à mesure que votre projet grandit.

Cependant, il y a un revers: ces cadres viennent avec un degré

C'est pourquoi, dans ce tutoriel, nous allons apprendre à construire un SPA à partir de zéro, sans utiliser de framework JavaScript côté client. Cela vous aidera à évaluer ce que ces cadres font réellement pour vous et à quel point il est logique d'en utiliser un. Il vous donnera également une compréhension des pièces qui composent un SPA typique et comment ils sont câblés ensemble.

Commençons …

Prérequis

Pour ce tutoriel, vous aurez besoin d'une connaissance fondamentale de JavaScript moderne et jQuery . Une certaine expérience en utilisant Handlebars Express et Axios sera utile, bien que ce ne soit pas strictement nécessaire. Vous aurez également besoin de la configuration suivante dans votre environnement:

Vous pouvez trouver le projet terminé sur notre dépôt GitHub .

Construire le projet

Nous allons construire un application de la monnaie simple qui fournira les fonctionnalités suivantes:

  • afficher les derniers taux de change
  • convertir d'une devise à l'autre
  • afficher les taux de change antérieurs basés sur une date spécifiée.

Nous allons utiliser le suivant les API REST en ligne gratuites pour implémenter ces fonctionnalités:

Fixer est une API bien construite qui fournit une API JSON de conversion de devises et de devises. Malheureusement, c'est un service commercial et le plan gratuit ne permet pas la conversion de devises. Nous aurons également besoin d'utiliser l'API Free Currency Converter. L'API de conversion a quelques limitations, ce qui, heureusement, n'affectera pas la fonctionnalité de notre application. Il peut être accédé directement sans nécessiter de clé API. Toutefois, Fixer requiert une clé API pour effectuer toute requête. Simplement inscrivez-vous sur leur site Web pour obtenir une clé d'accès pour le plan libre .

Idéalement, nous devrions être en mesure de construire l'application entière d'une seule page du côté client. Cependant, étant donné que nous traiterons des informations sensibles (notre clé API), il ne sera pas possible de les stocker dans notre code client. Cela rendra notre application vulnérable et ouverte à tout pirate junior pour contourner l'application et accéder aux données directement à partir de nos points de terminaison API. Pour protéger ces informations sensibles, nous devons le mettre dans le code du serveur. Nous allons donc configurer un serveur Express qui servira de proxy entre le code client et les services cloud. En utilisant un proxy, nous pouvons accéder à cette clé en toute sécurité, car le code serveur n'est jamais exposé au navigateur. Voici un diagramme illustrant le fonctionnement de notre projet achevé

 Plan du projet

Prenez note des paquets npm qui seront utilisés par chaque environnement – c'est-à-dire le navigateur (client) et le serveur. Maintenant que vous savez ce que nous allons construire, allez à la section suivante pour commencer à créer le projet.

Répertoires de projets et dépendances

Allez dans votre répertoire d'espace de travail et créez le dossier page unique- demande . Ouvrez le dossier dans VSCode ou votre éditeur favori et créez les fichiers et dossiers suivants en utilisant le terminal:

 touch .env .gitignore README.md server.js
mkdir public lib
mkdir public / js
Touchez public / index.html
touchez public / js / app.js

Ouvrez .gitignore et ajoutez les lignes suivantes:

 node_modules
.env

Ouvrez README.md et ajoutez les lignes suivantes:

 # Application page unique

Ceci est une démo de projet qui utilise Vanilla JS pour créer une application de page unique.

Ensuite, créez le fichier package.json en exécutant la commande suivante à l'intérieur du terminal:

 npm init -y

Vous devriez obtenir le contenu suivant généré pour vous:

 {
  "nom": "une seule page-application",
  "version": "1.0.0",
  "description": "Ceci est une démo de projet qui utilise Vanilla JS pour construire une application de page unique.",
  "main": "server.js",
  "directories": {
    "lib": "lib"
  },
  "scripts": {
    "test": "echo " Erreur: aucun test spécifié  "&& exit 1",
    "start": "nœud server.js"
  },
  "mots-clés": [],
  "auteur": "",
  "licence": "ISC"
}

Voyez à quel point la commande npm est commode? Le contenu a été généré en fonction de la structure du projet. Nous allons maintenant installer les dépendances de base nécessaires à notre projet. Exécutez la commande suivante dans votre terminal:

 npm install jquery sémantique-ui-css guidon vanilla-routeur express dotenv axios

Une fois les paquets terminés, passez à la section suivante pour commencer à construire la base de l'application

Application Base

Avant de commencer à écrire notre code frontal, nous devons implémenter un serveur … base de clients à partir de laquelle travailler. Cela signifie qu'une vue HTML de base est diffusée à partir d'un serveur Express. Pour des raisons de performances et de fiabilité, nous allons injecter des dépendances frontales directement à partir du dossier node_modules . Nous devrons configurer notre serveur Express d'une manière spéciale pour que cela fonctionne. Ouvrez server.js et ajoutez:

 require ('dotenv'). Config (); // Lire les fichiers .env
const express = require ('express');

const app = express ();
port const = process.env.PORT || 3000;

// Définir le dossier public en tant que root
app.use (express.static ('public'));

// Autorise l'accès frontal au dossier node_modules
app.use ('/ scripts', express.static (`$ {__ dirname} / node_modules /`));

// Ecoute des requêtes HTTP sur le port 3000
app.listen (port, () => {
  console.log ('écoute sur% d', port);
});

Cela nous donne un serveur Express de base. J'ai commenté le code, donc j'espère que cela vous donnera une assez bonne idée de ce qui se passe. Ensuite, ouvrez public / index.html et entrez:




  
  
  
  
   SPA Demo 


  
         
  
                    

Nous utilisons l'interface utilisateur sémantique pour le style. Reportez-vous à la documentation Semantic UI Menu pour comprendre le code utilisé pour notre barre de navigation. Accédez à votre terminal et démarrez le serveur:

 npm start

Ouvrir localhost: 3000 dans votre navigateur. Vous devriez avoir une page blanche avec seulement la barre de navigation montrant:

 Barre de navigation

Écrivons maintenant quelques modèles d'affichage pour notre application.

Modèles de squelette frontaux

Nous ' ll utilisera Handlebars pour écrire nos modèles. JavaScript sera utilisé pour rendre les modèles basés sur l'URL actuelle. Le premier modèle que nous allons créer sera pour afficher des messages d'erreur tels que 404 ou des erreurs de serveur. Placez ce code dans public / index.html juste après la section de navigation:

 
              

Ensuite, ajoutez les modèles suivants qui représenteront une vue pour chaque chemin d'URL que nous avons spécifié dans la barre de navigation:

      

Ensuite, compilons tous ces modèles dans public / js / app.js . Après la compilation, nous afficherons le template-rates et verrons à quoi il ressemble:

 window.addEventListener ('load', () => {
  const el = $ ('# app');

  // Compiler les modèles de guidon
  const errorTemplate = Handlebars.compile ($ ('# error-template'). html ());
  const ratesTemplate = Handlebars.compile ($ ('# rates-template'). html ());
  const exchangeTemplate = Handlebars.compile ($ ('# exchange-template') .html ());
  const historicTemplate = Handlebars.compile ($ ('# historique-template'). html ());

  const html = ratesTemplate ();
  el.html (html);
});

Notez que nous enveloppons tout le code client JavaScript dans un événement load . Ceci est juste pour s'assurer que toutes les dépendances ont été chargées et que le DOM a terminé le chargement. Rafraîchir la page et voir ce que nous avons:

 Les taux de change sont blancs

Nous progressons. Maintenant, si vous cliquez sur les autres liens, sauf taux de change le navigateur va essayer d'aller chercher une nouvelle page et se retrouver avec un message comme celui-ci: Can not GET /exchange.[19659003Nousconstruisonsuneapplicationd'uneseulepagecequisignifiequetoutel'actiondoitsefairesuruneseulepageNousavonsbesoind'unmoyendedireaunavigateurd'arrêterd'allerchercherdenouvellespageschaquefoisquel'URLchange

Routage côté client

Pour contrôler le routage dans l'environnement du navigateur, nous devons implémenter le routage côté client. Il existe de nombreuses bibliothèques de routage côté client qui peuvent vous aider. Pour notre projet, nous utiliserons vanilla router qui est un paquet de routage très facile à utiliser.

Si vous vous souvenez, nous avions déjà inclus toutes les bibliothèques JavaScript dont nous avons besoin dans index.html . Par conséquent, nous pouvons appeler la classe Router tout de suite. Supprimez les deux dernières instructions que vous avez ajoutées à app.js et remplacez-les par ce code:

 // Déclaration de routeur
const router = nouveau Routeur ({
  mode: 'histoire',
  page404: (chemin) => {
    const html = errorTemplate ({
      Couleur jaune',
      title: 'Erreur 404 - Page NON trouvée!',
      message: `Le chemin '/ $ {chemin}' n'existe pas sur ce site`,
    });
    el.html (html);
  },
});

router.add ('/', () => {
  laissez html = ratesTemplate ();
  el.html (html);
});

router.add ('/ exchange', () => {
  laissez html = exchangeTemplate ();
  el.html (html);
});

router.add ('/ historique', () => {
  laissez html = historicalTemplate ();
  el.html (html);
});

// Naviguer dans l'application vers l'URL actuelle
router.navigateTo (window.location.pathname);

 // Mettre en surbrillance Menu actif sur Actualiser / Page Reload
const link = $ (`a [href$='${window.location.pathname}']`);
link.addClass ('actif');

$ ('a'). on ('clic', (événement) => {
  // Bloquer le chargement de la page du navigateur
  event.preventDefault ();

  // Mettre en surbrillance le menu actif sur le clic
  const target = $ (event.target);
  $ ('. item'). removeClass ('actif');
  target.addClass ('actif');

  // Naviguer vers l'URL cliquée
  const href = target.attr ('href');
  const path = href.substr (href.lastIndexOf ('/'));
  router.navigateTo (chemin);
});

Prenez le temps de parcourir le code. J'ai ajouté des commentaires dans diverses sections pour expliquer ce qui se passe. Vous remarquerez que, dans la déclaration du routeur, nous avons spécifié la propriété page404 pour utiliser le modèle d'erreur. Testons maintenant les liens:

 Navigation historique vide

Les liens devraient maintenant fonctionner. Mais nous avons un problème. Cliquez sur le lien / échange ou historique puis actualisez le navigateur. Nous obtenons la même erreur qu'avant – Can not GET / exchange . Pour résoudre ce problème, rendez-vous sur server.js et ajoutez cette instruction juste avant le code d'écoute:

 // Redirigez tout le trafic vers index.html
app.use ((req, res) => res.sendFile (`$ {__ dirname} / public / index.html`));

Vous devrez redémarrer le serveur en utilisant Ctrl + C et en exécutant npm start . Retournez dans le navigateur et essayez de vous rafraîchir. Vous devriez maintenant voir le rendu de la page correctement. Maintenant, essayons d'entrer un chemin inexistant dans l'URL comme / échanges . L'application doit afficher un message d'erreur 404:

 404 erreur

Nous avons maintenant implémenté le code nécessaire pour créer notre squelette d'une seule page. Commençons maintenant à dresser la liste des derniers taux de change

Les derniers taux de change

Pour cette tâche, nous utiliserons le point de terminaison du dernier fixing de Fixer . Ouvrez le fichier .env et ajoutez votre clé API. Nous spécifierons également la période d'expiration et les symboles que nous lirons sur notre page. N'hésitez pas à augmenter la valeur du délai si vous avez une connexion Internet plus lente:

 API_KEY = 
PORT = 3000
TIMEOUT = 5000
SYMBOLES = EUR, USD, GBP, AUD, BTC, KES, JPY, CNY

Ensuite, créez le fichier lib / fixer-service.js . C'est là que nous allons écrire du code d'assistance pour notre serveur Express afin de demander facilement des informations à Fixer. Copiez le code suivant:

 require ('dotenv'). Config ();
const axios = require ('axios');

symboles const = process.env.SYMBOLS || «EUR, USD, GBP»;

// Déclaration du client Axios
const api = axios.create ({
  baseURL: 'http://data.fixer.io/api',
  params: {
    access_key: process.env.API_KEY,
  },
  timeout: process.env.TIMEOUT || 5000,
});

// Fonction de requête GET générique
const get = async (url) => {
  const response = attendez api.get (url);
  const {data} = réponse;
  if (data.success) {
    renvoyer des données;
  }
  throw new Error (data.error.type);
}

module.exports = {
  getRates: () => get (`/ latest & symbols = $ {symboles} & base = EUR`),
}

Encore une fois, prenez le temps de parcourir le code pour comprendre ce qui se passe. Si vous n'êtes pas sûr, vous pouvez également consulter la documentation de dotenv axios et lire les modules d'exportation . Faisons maintenant un test rapide pour confirmer que la fonction getRates () fonctionne

Ouvrez server.js et ajoutez ce code:

 const {getRates} = require ( './lib/fixer-service');

...
// Placer ce bloc en bas
test const = async () => {
  const data = wait getRates ();
  console.log (données);
}

tester();

Exécutez npm start ou serveur de nœud . Après quelques secondes, vous devriez obtenir la sortie suivante:

 {
  succès: vrai,
  horodatage: 1523871848,
  base: 'EUR',
  date: '2018-04-16',
  les taux: {
    EUR: 1,
    USD: 1.23732,
    GBP: 0.865158,
    AUD: 1.59169,
    CTB: 0,000153,
    KES: 124.226892,
    JPY: 132.608498,
    CNY: 7.775567
  }
}

Si vous obtenez quelque chose de similaire à ce qui précède, cela signifie que le code fonctionne. Les valeurs seront bien sûr différentes, puisque les taux changent tous les jours. Maintenant commentez le bloc de test et insérez ce code juste avant l'instruction qui redirige tout le trafic vers index.html :

 // Gestionnaire d'erreurs express
const errorHandler = (err, req, res) => {
  if (err.response) {
    // La requête a été faite et le serveur a répondu avec un code d'état
    // qui tombe hors de la plage de 2xx
    res.status (403) .send ({title: 'Le serveur a répondu avec une erreur', message: err.message});
  } else if (err.request) {
    // La demande a été faite mais aucune réponse n'a été reçue
    res.status (503) .send ({title: 'Impossible de communiquer avec le serveur', message: err.message});
  } autre {
    // Quelque chose s'est produit lors de la configuration de la requête qui a déclenché une erreur
    res.status (500) .send ({title: 'Une erreur inattendue s'est produite', message: err.message});
  }
}

// Récupérer les derniers taux de change
app.get ('/ api / rates', async (req, res) => {
  essayez {
    const data = wait getRates ();
    res.setHeader ('Content-Type', 'application / json');
    res.send (données);
  } catch (erreur) {
    errorHandler (erreur, req, res);
  }
});

Comme nous pouvons le voir, il existe une fonction de gestionnaire d'erreur personnalisée conçue pour gérer différents scénarios d'erreur, qui peuvent survenir lors de l'exécution du code du serveur. Lorsqu'une erreur se produit, un message d'erreur est construit et renvoyé au client.

Vérifions que ce bit de code fonctionne. Redémarrez le serveur Express et naviguez votre navigateur à cette URL: localhost: 3000 / api / rates . Vous devriez voir le même résultat JSON qui a été affiché dans la console. Nous pouvons maintenant implémenter une vue qui affichera cette information dans une table soignée et élégante.

Ouvrez public / index.html et remplacez le taux-template avec ce code: [19659050] Monnaie


Date

{{date}}

Base

{{base}}

Taux [1965#9290].
        

{{/ chaque}}
      

    

Code Taux
{{@ key}} {{this}}

  


Rappelez-vous que nous utilisons l'interface utilisateur sémantique pour nous fournir un style. J'aimerais que vous prêtiez une attention particulière au composant Chargement du chargement . Ce sera une indication pour laisser les utilisateurs savoir que quelque chose se passe que l'application récupère les données. Nous utilisons également l'interface de table pour afficher les taux. S'il vous plaît allez si la documentation liée si vous êtes nouveau à Semantic.

Maintenant mettons à jour notre code dans public / js / app.js pour faire usage de ce nouveau modèle. Remplacez la première route.add ('/') avec ce code:

 // Instancier un gestionnaire d'API
const api = axios.create ({
  baseURL: 'http: // localhost: 3000 / api',
  délai d'attente: 5000,
});

// Afficher la bannière d'erreur
const showError = (erreur) => {
  const {titre, message} = erreur.response.data;
  const html = errorTemplate ({couleur: 'red', titre, message});
  el.html (html);
}

// Afficher les derniers taux de change
router.add ('/', async () => {
  // Afficher le chargeur en premier
  laissez html = ratesTemplate ();
  el.html (html);
  essayez {
    // Charger les taux de change
    const response = attendez api.get ('/ rates');
    const {base, date, rates} = réponse.data;
    // Afficher le tableau des tarifs
    html = ratesTemplate ({base, date, rates});
    el.html (html);
  } catch (erreur) {
    showError (erreur);
  } enfin {
    // Supprimer le statut du chargeur
    $ ('. loading'). removeClass ('chargement');
  }
});

Le premier bloc de code instancie un client API pour communiquer avec notre serveur proxy. Le deuxième bloc est une fonction globale pour gérer les erreurs. Son travail consiste simplement à afficher une bannière d'erreur en cas de problème sur le serveur. Le troisième bloc est l'endroit où nous obtenons des données de taux à partir du point de terminaison localhost: 3000 / api / rates et le transmettons au taux-template pour afficher l'information.

navigateur. Vous devriez maintenant avoir la vue suivante:

 Taux de change

Ensuite, nous allons construire une interface pour convertir les devises.

Conversion d'échange

Pour la conversion de devises, nous allons utiliser deux points de terminaison:

Nous avons besoin du point de terminaison des symboles pour obtenir une liste des codes de devise pris en charge. Nous utiliserons ces données pour remplir les listes déroulantes que les utilisateurs utiliseront pour sélectionner les devises à convertir. Ouvrez lib / fixateur-service.js et ajoutez cette ligne juste après la fonction getRates () :

 getSymbols: () => get ('/ symbols'),

Créez un autre fichier d'assistance, lib / free-currency-service.js et ajoutez le code suivant:

 require ('dotenv'). Config ();
const axios = require ('axios');

const api = axios.create ({
  baseURL: 'https://free.currencyconverterapi.com/api/v5',
  timeout: process.env.TIMEOUT || 5000,
});

module.exports = {
  convertCurrency: async (de, à) => {
    const response = attendre api.get (`/ convertir? q = $ {de} _ $ {en} & compact = y`);
    const key = Object.keys (response.data) [0];
    const {val} = response.data [key];
    return {rate: val};
  },
}

Cela nous aidera à obtenir le taux de conversion d'une devise à l'autre gratuitement. Dans le code client, nous devrons calculer le montant de la conversion en multipliant le montant par le taux. Maintenant, ajoutons ces deux méthodes de service à notre code serveur Express. Ouvrez server.js et mettez à jour en conséquence:

 const {getRates, getSymbols,} = require ('./ lib / fixateur-service');
const {convertCurrency} = require ('./ lib / free-currency-service');
...
// Insérer à droite après avoir '/ api / rates', juste avant l'instruction de redirection

// Récupère les symboles
app.get ('/ api / symbols', async (req, res) => {
  essayez {
    const data = wait getSymbols ();
    res.setHeader ('Content-Type', 'application / json');
    res.send (données);
  } catch (erreur) {
    errorHandler (erreur, req, res);
  }
});

// Convertir en monnaie
app.post ('/ api / convert', async (req, res) => {
  essayez {
    const {de, à} = req.body;
    const data = wait convertCurrency (de, à);
    res.setHeader ('Content-Type', 'application / json');
    res.send (données);
  } catch (erreur) {
    errorHandler (erreur, req, res);
  }
});

Maintenant, notre serveur proxy devrait être capable d'obtenir des symboles et des taux de conversion. Prenez note que / api / convert est une méthode POST. Nous utiliserons un formulaire du côté client pour créer l'interface de conversion de devise. N'hésitez pas à utiliser la fonction de test pour confirmer que les deux points de terminaison fonctionnent. Voici un exemple:

 // Test Endpoint Symbols
test const = async () => {
  const data = wait getSymbols ();
  console.log (données);
}

// Test du point de fin de conversion de devise
test const = async () => {
  const data = wait convertCurrency ('USD', 'KES');
  console.log (données);
}

Vous devrez redémarrer le serveur pour chaque test. N'oubliez pas de commenter les tests une fois que vous avez confirmé que le code fonctionne jusqu'à présent. Travaillons maintenant sur notre interface de conversion de devises. Ouvrez public / index.html et mettez à jour le modèle d'échange en remplaçant le code existant par ceci:

 

Prenez votre temps pour parcourir le scénario et comprendre ce qui se passe. Nous utilisons la forme d'interface utilisateur sémantique pour construire l'interface. Nous utilisons également la notation Handlebars pour remplir les listes déroulantes. Voici le format JSON utilisé par le point de terminaison Symboles de Fixer:

 {
  "succès": vrai,
  "symboles": {
    "AED": "Dirham des Emirats Arabes Unis",
    "AFN": "Afghan Afghani",
    "ALL": "Lek Albanais",
    "AMD": "Dram arménien",
  }
}

Prenez note que les données des symboles sont au format carte. Cela signifie que les informations sont stockées en tant que clés {{@ key}} et que la valeur {{this}} paires. Commençons maintenant par mettre à jour public / js / app.js et le faire fonctionner avec le nouveau modèle. Ouvrez le fichier et remplacez le code de route existant pour / exchange par ce qui suit:

 // Effectuer une requête POST, calculer et afficher les résultats de conversion
const getConversionResults = async () => {
  // Extraire les données de formulaire
  const de = $ ('# from'). val ();
  const à = $ ('#'). val ();
  const montant = $ ('# montant'). val ();
  // Envoyer des données de publication au serveur Express (proxy)
  essayez {
    const response = attendez api.post ('/ convert', {from, to});
    const {rate} = réponse.data;
    résultat de const = taux * montant;
    $ ('# result'). html (`$ {to} $ {résultat}`);
  } catch (erreur) {
    showError (erreur);
  } enfin {
    $ ('# result-segment'). removeClass ('chargement');
  }
}

// Gérer le bouton Convertir le clic sur l'événement
const convertRatesHandler = () => {
  if ($ ('. ui.form'). form ('est valide')) {
    // masque le message d'erreur
    $ ('.ui.error.message'). hide ();
    // Publier sur le serveur Express
    $ ('# result-segment'). addClass ('chargement');
    getConversionResults ();
    // Empêche la page de soumettre au serveur
    return false;
  }
  retourner vrai;
}

router.add ('/ exchange', async () => {
  // Afficher le chargeur en premier
  laissez html = exchangeTemplate ();
  el.html (html);
  essayez {
    // Charger les symboles
    const response = attendez api.get ('/ symbols');
    const {symbols} = réponse.data;
    html = exchangeTemplate ({symboles});
    el.html (html);
    $ ('. loading'). removeClass ('chargement');
    // Valider les entrées de formulaire
    $ ('.ui.form') .formulaire ({
      des champs: {
        de: 'vide',
        à vider',
        montant: 'décimal',
      },
    });
    // Spécifier le gestionnaire de soumission
    $ ('. submit'). click (convertRatesHandler);
  } catch (erreur) {
    showError (erreur);
  }
});

Actualisez la page. Vous devriez maintenant avoir la vue suivante:

 UI d'échange

Sélectionnez des devises de votre choix et entrez un montant. Puis cliquez sur le bouton Convert :

 Erreur d'échange

Oups! Nous venons de frapper un scénario d'erreur. Au moins, nous savons que notre code de traitement des erreurs fonctionne. Pour comprendre pourquoi l'erreur se produit, revenez au code du serveur et examinez la fonction / api / convert . Plus précisément, regardez la ligne qui indique const {de, to} = req.body; .

Il semble qu'Express ne puisse pas lire les propriétés de l'objet request . Pour résoudre ce problème, nous devons installer un middleware qui peut vous aider:

 npm install body-parser

Ensuite, mettez à jour le code du serveur comme suit:

 const bodyParser = require ('body-parser');
...

/ ** Placez ce code juste avant la fonction gestionnaire d'erreur ** /

// Analyse les données POST en tant que données codées d'URL
app.use (bodyParser.urlencoded ({
  étendu: vrai,
}));

// Analyse les données POST en tant que JSON
app.use (bodyParser.json ());

Redémarrez le serveur et actualisez le navigateur. Essayez de faire une autre conversion. Il devrait maintenant fonctionner

 Conversion d'échange

Concentrons-nous maintenant sur le dernier bit – les taux de change historiques. Commençons par les vues.

Taux de change historiques

La mise en œuvre de cette fonctionnalité s'apparentera à la combinaison des tâches des première et deuxième pages. Nous allons construire une forme minuscule où l'utilisateur devra entrer une date. Lorsque l'utilisateur clique sur Envoyer, les taux de change pour la date spécifiée seront affichés sous forme de tableau. Nous utiliserons le Historical Rates Endpoint de l'API Fixer pour y parvenir. La requête API ressemble à ceci:

 https://data.fixer.io/api/2013-12-24
    ? access_key = API_KEY
    & base = GBP
    & symboles = USD, CAD, EUR

Et la réponse ressemblera à ceci:

 {
  "succès": vrai,
  "historique": vrai,
  "date": "2013-12-24",
  "horodateur": 1387929599,
  "base": "GBP",
  "les taux": {
    "USD": 1.636492,
    "EUR": 1.196476,
    "CAD": 1.739516
  }
}

Ouvrez lib / fixateur-service.js et le point de terminaison des taux historiques comme ceci:

 ...
  / ** Placer juste après getSymbols ** /
  getHistoricalRate: date => get (`/ $ {date} & symboles = $ {symboles} & base = EUR`),
...

Ouvrez server.js et ajoutez le code suivant:

 ...
const {getRates, getSymbols, getHistoricalRate} = require ('./ lib / fixateur-service');
...
/ ** Placez ceci après la fonction post '/ api / convert' ** /

// Récupère les taux de change par date
app.post ('/ api / historique', async (req, res) => {
  essayez {
    const {date} = req.body;
    const data = attend getHistoricalRate (date);
    res.setHeader ('Content-Type', 'application / json');
    res.send (données);
  } catch (erreur) {
    errorHandler (erreur, req, res);
  }
});
...

Si vous avez des doutes quant à la disposition du code, veuillez vous reporter au fichier complet server.js sur GitHub . N'hésitez pas à écrire un test rapide pour confirmer que le point de terminaison historique fonctionne:

 const test = async () => {
  const data = await getHistoricalRate ('2012-07-14');
  console.log (données);
}

tester();

Ne oubliez pas de commenter le bloc de test une fois que vous confirmez que tout fonctionne. Maintenant, travaillons maintenant sur le code client.

Ouvrez index.html . Supprimez le modèle historique existant que nous avons utilisé comme espace réservé et remplacez-le par ce qui suit:

 

Regardez d'abord le formulaire. Une chose que je voudrais souligner est que l'interface utilisateur sémantique n'a pas officiellement d'entrée de date. Cependant, grâce à la contribution de Michael de Hoog nous avons à notre disposition le module Semantic-UI-Calendar . Il suffit de l'installer en utilisant npm:

 npm install semantic-ui-calendar

Retournez à public / index.html et incluez-le dans la section des scripts:

 ...   ....

Pour afficher les taux historiques, nous allons simplement réutiliser le modèle de taux . Ensuite, ouvrez public / js / app.js et mettez à jour le code de route existant pour / historique :

 const getHistoricalRates = async () => {
  const date = $ ('# date'). val ();
  essayez {
    const response = wait api.post ('/ historique', {date});
    const {base, rates} = réponse.data;
    const html = ratesTemplate ({base, date, rates});
    $ ('# historique-table'). html (html);
  } catch (erreur) {
    showError (erreur);
  } enfin {
    $ ('. segment'). removeClass ('chargement');
  }
}

const historicRatesHandler = () => {
  if ($ ('. ui.form'). form ('est valide')) {
    // masque le message d'erreur
    $ ('.ui.error.message'). hide ();
    // Indique l'état de chargement
    $ ('. segment'). addClass ('chargement');
    getHistoricalRates ();
    // Empêche la page de soumettre au serveur
    return false;
  }
  retourner vrai;
}

router.add ('/ historique', () => {
  // Afficher le formulaire
  const html = historyTemplate ();
  el.html (html);
  // Activer le sélecteur de date
  $ ('# calendrier'). calendar ({
    tapez: 'date',
    formatter: {// formater la date en aaaa-mm-jj
      date: date => new Date (date) .toISOString (). split ('T') [0],
    },
  });
  // Valider l'entrée Date
  $ ('.ui.form') .formulaire ({
    des champs: {
      date: 'vide',
    },
  });
  $ ('. submit'). click (historicalRatesHandler);
});

Encore une fois, prenez le temps de lire les commentaires et de comprendre le code et ce qu'il fait. Redémarrez ensuite le serveur, actualisez le navigateur et accédez au chemin / historique . Choisissez n'importe quelle date avant l'année 1999 puis cliquez sur Fetch Rates . Vous devriez avoir quelque chose comme:

 Todo taux historiques

Si vous choisissez une date avant l'année 1999 ou une date dans le futur, une bannière d'erreur sera affichée lorsque vous soumettez le formulaire.

 Erreur de taux historique Todo

Résumé

Maintenant que nous sommes arrivés à la fin du tutoriel, vous devriez voir qu'il n'est pas si difficile de construire une application monopage basée sur des API REST sans en utilisant un cadre. Mais il y a quelques choses qui devraient nous intéresser:

  • DOM Performance . Dans notre code côté client, nous manipulons directement le DOM. Cela peut rapidement devenir incontrôlable au fur et à mesure que le projet prend de l'ampleur, ce qui fait que l'assurance-chômage devient léthargique.

  • Performance du navigateur . Il y a un certain nombre de bibliothèques frontales que nous avons chargées en tant que scripts dans index.html ce qui est acceptable pour le développement. Pour le déploiement en production, nous avons besoin d'un système permettant de regrouper tous les scripts afin que les navigateurs utilisent une seule requête pour charger les ressources JavaScript nécessaires.

  • Code monolithique . Pour le code serveur, il est plus facile de décomposer le code en parties modulaires puisqu'il s'exécute dans un environnement de noeud. Cependant, pour le code côté client, il n'est pas facile de s'organiser en modules, sauf si vous utilisez un bundler comme webpack .

  • Tests . Jusqu'à présent, nous avons fait des tests manuels. Pour une application prête pour la production, nous devons mettre en place un cadre de test comme Jasmine, Mocha ou Chai pour automatiser ce travail. Cela aidera à prévenir les erreurs récurrentes.

Ce ne sont là que quelques-uns des nombreux problèmes auxquels vous serez confronté lorsque vous approcherez le développement d'un projet sans utiliser de framework. Utiliser quelque chose comme Angular, React ou Vue vous aidera à atténuer beaucoup de ces problèmes. J'espère que ce tutoriel a été utile et qu'il vous aidera à devenir un développeur JavaScript professionnel.




Source link