Application Nuxt.js du kit d'interface utilisateur au déploiement

Bonjour, Habr!



J'ai écrit ce didacticiel détaillé, étape par étape, afin que chacun puisse créer sa propre application en utilisant le framework Nuxt.js à partir de zéro.



Dans cet article, nous aborderons les bases, les bases de la création d'une application Nuxt.js:



  • création et configuration de projet,
  • actifs et statiques: styles, polices, images, publications,
  • création de composants,
  • création de pages et de mises en page,
  • déploiement d'application (déploiement).


Voyez ce qui s'est passé!



Un peu sur Nuxt.js



Nuxt est un framework Vue de haut niveau. Nuxt.js vous permet de développer des applications web isomorphes prêtes à l'emploi en faisant abstraction des détails de distribution du code serveur et client. Grâce à cette approche, nous gagnons du temps et pouvons nous concentrer sur le développement.



Les principaux avantages de Nuxt:



  • SPA, SSR et prerender sont déjà configurés; tout ce qu'il nous faut, c'est indiquer. Dans cette application, nous utilisons un prerender pour le mode produit, c'est-à-dire que nous allons générer toutes les pages du site à l'avance, puis les déployer sur l'hébergement pour distribuer la statique.
  • Un excellent référencement pour tous les moteurs de recherche est le résultat de l'utilisation de SSR ou de pré-rendu.
  • . js chunks, css styles API ( webpack 4, Nuxt).
  • Google Lighthouse / Page Speed. 100/100 .
  • CSS Modules, Babel, Postscc create-nuxt-app.
  • .
  • 50 Vue.js.


On peut parler des avantages de Nuxt pendant très longtemps. C'est le framework que j'aime vraiment pour sa facilité d'utilisation et sa capacité à créer des applications flexibles et facilement évolutives. Donc, je propose de commencer et de voir tous les avantages dans la pratique.

Plus d'informations sur Nuxt.js sur le site officiel . Des guides détaillés sont également disponibles ici .



Conception



Une conception bien pensée et prête à l'emploi, ou encore mieux un kit d'interface utilisateur, accélérera et simplifiera considérablement le développement de toute application. S'il n'y a pas de concepteur d'interface utilisateur gratuit à proximité, ce n'est pas grave. Dans le cadre de nos instructions, nous pouvons le gérer nous-mêmes!



Surtout pour cet article, j'ai préparé un design de blog dans un style moderne et minimaliste avec des fonctionnalités simples, assez pour démontrer les capacités de Nuxt.



Pour le développement, j'ai utilisé le service en ligne Figma. La conception et le kit d'interface utilisateur sont disponibles ici . Vous pouvez copier ce modèle et l'utiliser dans votre projet.



Création de projet



Pour créer un projet, nous utiliserons l'utilitaire Nuxt create-nuxt-app des développeurs Nuxt , qui nous permet de configurer le modèle d'application via le cli.



Nous initialisons le projet en spécifiant son nom:



npx create-nuxt-app nuxt-blog
      
      





De plus, en plusieurs étapes, l'utilitaire nous proposera de choisir un ensemble de bibliothèques et de packages préférés, après quoi il les téléchargera, les configurera et les configurera indépendamment pour le projet.



Vous pouvez voir une liste complète des options sélectionnées sur Github .



Pour ce projet, la configuration avec Typescript sera utilisée.



Lors du développement dans Vue avec Typescript, vous pouvez utiliser deux API: API Options ou API de classe .



Ils ne diffèrent pas fonctionnellement les uns des autres, mais ils ont une syntaxe différente. Personnellement, la syntaxe de l'API Options est plus proche de moi, elle sera donc utilisée dans notre projet.



Après avoir créé le projet, nous pouvons exécuter notre application en utilisant la commande: npm run dev. Il sera désormais disponible sur localhost: 3000.



Nuxt utilise webpack-dev-server avec HMR installé et configuré en tant que serveur local , ce qui rend le développement rapide et confortable.



Puisque nous créons une version de démonstration de l'application, je n'écrirai pas de tests pour celle-ci. Mais je recommande fortement de ne pas négliger les tests d'application dans le développement commercial.



Si vous n'avez jamais abordé ce sujet auparavant, je vous conseille de faire attention à Jest - un outil très simple, mais en même temps puissant qui prend en charge le travail avec Nuxt en conjonction avec vue-test-utils .



Structure du projet



Nuxt crée par défaut un répertoire et une structure de fichiers adaptés pour un démarrage rapide du développement. Pour notre projet, une telle structure convient parfaitement, nous ne la changerons donc pas. Vous pouvez en savoir plus sur la fonction des différents répertoires sur le site Web de Nuxt .



-- Assets

-- Static

-- Pages

-- Middleware

-- Components

-- Layouts

-- Plugins

-- Store

-- nuxt.config.js

-- ...other files














Création d'applications



Avant d'écrire le code,



procédons comme suit: 1. Supprimez les composants de démarrage et les pages générées par Nuxt.

2. Installez pug et scss pour notre commodité et pour gagner du temps pendant le développement. Exécutons la commande:



npm i --save-dev pug pug-plain-loader node-sass sass-loader fibers
      
      





Après cela, l'utilisation de l'attribut lang pour les balises de modèle et de style deviendra disponible:



<template lang="pug"></template>

<style lang="scss"></style>
      
      





3. Ajoutez la prise en charge du sélecteur :: v-deep deep à la configuration stylelint, ce qui permettra de styliser les composants enfants, en ignorant la portée. Vous pouvez en savoir plus sur ce sélecteur ici.



{
  rules: {  
    'at-rule-no-unknown': null,  
    'selector-pseudo-element-no-unknown': [  
      true,  
      {  
        ignorePseudoElements: ['v-deep'],  
      },  
    ],  
  },
}
      
      





Tous les préparatifs sont terminés, passez à l'étape suivante.



Des postes



Les publications seront stockées dans le répertoire content / posts, que nous créerons à la racine du projet sous la forme d'un ensemble de fichiers de démarque.



Créons 5 petits fichiers afin que nous puissions commencer à travailler avec eux tout de suite. Pour simplifier, nous utiliserons les noms 1.md, 2.md, etc.



Dans le répertoire de contenu, créez le fichier Posts.d.ts, dans lequel nous définissons les types de l'objet contenant toutes les informations nécessaires sur l'article:



export type Post = {  
  id: number  
  title: string
  desc: string
  file: string
  img: string  
}
      
      





Je pense que la signification de tous les champs devrait être claire à partir des noms.



Passez. Dans le même répertoire, créez un autre fichier appelé posts.ts avec le contenu suivant:



import { Post } from './Post'  

export default [  
  {
    id: 1,  
    title: 'Post 1',  
    desc:  
      'A short description of the post to keep the user interested.' +  
      ' Description can be of different lengths, blocks are aligned' +  
      ' to the height of the block with the longest description',  
    file: 'content/posts/1.md',
    img: 'assets/images/1.svg',
  },  

  ...

  {  
    id: 5,  
    title: 'Post 5',  
    desc:  
      'A short description of the post to keep the user interested.' +  
      ' Description can be of different lengths, blocks are aligned' +  
      ' to the height of the block with the longest description',  
    file: 'content/posts/5.md',
    img: 'assets/images/5.svg',
  },  
] as Post[]
      
      





Dans la propriété img, nous faisons référence aux images dans le répertoire assets / images, mais nous n'avons pas encore créé ce répertoire, faisons-le maintenant.



Ajoutons maintenant les images au format .svg au répertoire créé avec les noms que nous avons spécifiés ci-dessus.



Je vais prendre 5 images de unDraw . Cette excellente ressource est constamment mise à jour et contient de nombreuses images svg gratuites.



Maintenant que tout est prêt, le répertoire de contenu doit ressembler à ceci: Et le sous-répertoire des images doit apparaître dans le répertoire des ressources avec le contenu suivant:



content/

-- posts.ts

-- Posts.d.ts

-- posts/

---- 1.md

---- 2.md

---- 3.md

---- 4.md

---- 5.md












assets/

-- images/

---- 1.svg

---- 2.svg

---- 3.svg

---- 4.svg

---- 5.svg

...








Récupération dynamique des fichiers



Puisque nous recevrons des images et des fichiers avec le texte des articles de manière dynamique, nous devons implémenter un mixin global, que nous pouvons utiliser plus loin dans tous les composants.



Pour ce faire, créez un sous-répertoire mixins dans le répertoire plugins, et dans celui-ci un fichier getDynamicFile.ts avec le contenu suivant:



import Vue from 'vue'  
  
export const methods = {  
  getDynamicFile(name: string) {  
    return require(`@/${name}`)
 },  
}  
  
Vue.mixin({  
  methods,  
})
      
      





Il ne nous reste plus qu'à activer ce mixin dans le fichier nuxt.config.js:



{
  plugins: [  
    '~plugins/mixins/getDynamicFile.ts',  
  ],
}
      
      





Polices



Après l'étape de création des articles, connectez les polices. Le moyen le plus simple de le faire est la merveilleuse bibliothèque Webfontloader , qui vous permet d'obtenir n'importe quelle police de Google Fonts . Cependant, dans le développement commercial, des polices personnalisées sont souvent utilisées, alors regardons juste ce cas ici.



Rubik a été choisi comme police pour notre application, qui est distribuée sous la licence Open Font . Vous pouvez tout télécharger à partir des mêmes polices Google .



Veuillez noter que dans l'archive téléchargée, les polices seront au format otf, mais comme nous travaillons avec le Web, les formats woff et woff2 seront le meilleur choix pour nous. Ils sont plus petits que tout autre format, mais sont parfaitement pris en charge dans tous les navigateurs modernes. Pour convertir otf aux formats dont nous avons besoin, vous pouvez utiliser l'un des nombreux services en ligne gratuits.



Donc, nous avons les polices dans les formats dont nous avons besoin, il est temps de les inclure dans le projet. Pour ce faire, créez un sous-répertoire de polices dans le répertoire statique et ajoutez-y nos polices. Créons un fichier fonts.css dans le même répertoire, qui sera chargé de connecter nos polices dans l'application avec le contenu suivant:



@font-face {  
  font-family: "Rubik-Regular";  
  font-weight: normal;  
  font-style: normal;  
  font-display: swap;  
  src:  
	  local("Rubik"),  
	  local("Rubik-Regular"),  
	  local("Rubik Regular"),  
	  url("/fonts/Rubik-Regular.woff2") format("woff2"),  
	  url("/fonts/Rubik-Regular.woff") format("woff");  
}  
  
...
      
      





Le contenu complet du fichier peut être vu dans le référentiel .



Il y a 2 choses à noter:



1. Nous spécifions font-display: swap ;, définissant comment la police connectée via font-face sera affichée selon qu'elle est chargée et prête à l'emploi.

Dans ce cas, nous ne définissons pas la période de blocage et définissons une période de substitution infinie. Autrement dit, le chargement de la police se produit en arrière-plan et ne bloque pas le chargement de la page, et la police sera affichée lorsqu'elle sera prête.



2. Dans src, nous spécifions l'ordre de démarrage par priorité. Tout d'abord, nous vérifions si la police souhaitée est installée sur l'appareil de l'utilisateur en vérifiant les variantes possibles du nom de la police. Si nous ne le trouvons pas, nous vérifions si le navigateur prend en charge le format woff2 plus moderne, et sinon, passons au format woff suivant. Il est possible que l'utilisateur utilise un navigateur obsolète (par exemple, IE <9), dans ce cas, dans ce qui suit, nous indiquerons les polices intégrées au navigateur comme solution de secours.



Après avoir créé le fichier avec les règles de chargement des polices, vous devez le connecter dans l'application - dans le fichier nuxt.config.js dans la section head:



{
  head: {  
    link: [  
      {  
        as: 'style',  
        rel: 'stylesheet preload prefetch',  
        href: '/fonts/fonts.css',  
      },  
    ],  
  },
}
      
      





Notez qu'ici, comme précédemment, nous utilisons les propriétés de préchargement et de prélecture, définissant ainsi une priorité élevée dans le navigateur pour télécharger ces fichiers et ne pas bloquer le rendu de la page.



Ajoutons immédiatement au répertoire favicon statique de notre application, qui peut être généré à l'aide de n'importe quel service en ligne gratuit.



Le répertoire statique ressemble maintenant à ceci: Passez à l'étape suivante.



static/

-- fonts/

---- fonts.css

---- Rubik-Bold.woff2

---- Rubik-Bold.woff

---- Rubik-Medium.woff2

---- Rubik-Medium.woff

---- Rubik-Regular.woff2

---- Rubik-Regular.woff

-- favicon.ico












Styles réutilisables



Dans notre projet, tous les styles utilisés sont décrits par un seul ensemble de règles, ce qui rend le développement beaucoup plus facile, alors transférons ces styles de Figma vers les fichiers du projet.

Dans le répertoire assets, créez un sous-répertoire styles, dans lequel nous stockerons tous les styles réutilisés dans le projet. À son tour, le répertoire styles contiendra le fichier variables.scss avec toutes nos variables scss.



Le contenu du fichier peut être vu dans le référentiel .



Nous devons maintenant connecter ces variables au projet afin qu'elles soient disponibles dans l'un de nos composants. Nuxt utilise le module @ nuxtjs / style-resources à cet effet .



Installons ce module:



npm i @nuxtjs/style-resources
      
      





Et ajoutez les lignes suivantes à nuxt.config.js:



{
  modules: [
    '@nuxtjs/style-resources',
  ],

  styleResources: {  
    scss: ['./assets/styles/variables.scss'],  
  },
}
      
      





Bien! Les variables de ce fichier seront disponibles dans n'importe quel composant.



L'étape suivante consiste à créer quelques classes d'assistance et styles globaux qui seront utilisés dans toute l'application. Cette approche vous permettra de gérer de manière centralisée les styles communs et d'adapter rapidement l'application si l'apparence des mises en page est modifiée par le concepteur.



Créons un sous-répertoire global dans le répertoire assets / styles avec les fichiers suivants:



1. typography.scss - le fichier contiendra toutes les classes d'aide pour le texte, y compris les liens.

Notez que ces classes d'assistance changent de style en fonction de la résolution de l'appareil de l'utilisateur: smartphone ou PC.



2. transitions.scss - le fichier contiendra des styles d'animation globaux, à la fois pour les transitions entre les pages et pour les animations à l'intérieur des composants, si nous en avons besoin à l'avenir.



3. other.scss - le fichier contiendra des styles globaux, qui n'ont pas encore été sélectionnés dans un groupe séparé.



La classe .page sera utilisée comme conteneur commun pour tous les composants de la page et formera le remplissage correct sur la page.



La classe .section sera utilisée pour marquer les limites des boîtes logiques, et la classe .content sera utilisée pour restreindre la largeur du contenu et le centrer sur la page.



Nous verrons des exemples d'utilisation de ces classes plus tard lorsque nous commencerons à implémenter des composants et des pages.



4. index.scss - un fichier général qui sera utilisé comme point d'exportation unique pour tous les styles globaux.



Le contenu complet des fichiers peut être vu sur Github .



À ce stade, nous inclurons ces styles globaux afin qu'ils deviennent disponibles dans toute l'application. Pour cette tâche, Nuxt nous fournit une section css dans le fichier nuxt.config.js:



{
  css: ['~assets/styles/global'],
}
      
      





Il vaut la peine de dire qu'à l'avenir, lors de l'affectation de classes css, la logique suivante sera utilisée:



1. Si une balise a à la fois des classes d'assistance et des classes locales, les classes locales seront directement ajoutées à la balise, par exemple, p .some-local-class et les classes d'assistance sont spécifiées dans la propriété class, par exemple, class = "body3 medium".



2. Si une balise n'a que des classes d'assistance ou uniquement des classes locales, elles seront directement ajoutées à la balise.



J'utilise cette technique pour ma commodité, pour distinguer visuellement immédiatement les classes globales et locales.



Avant le développement, installons et activons reset.css afin que notre mise en page soit la même dans tous les navigateurs. Pour ce faire, installez le package requis:



npm i reset-css
      
      





Et nous l'inclurons dans le fichier nuxt.config.js dans la section css déjà familière, qui ressemblera maintenant à ceci:



{
  css: [
    '~assets/styles/global',
    'reset-css/reset.css',
  ],
}
      
      





Arrivé? Si tel est le cas, nous sommes prêts à passer à l'étape suivante!



Mises en page



Dans Nuxt, les mises en page sont des wrappers sur les pages qui vous permettent de réutiliser des composants communs entre eux et d'implémenter la logique commune nécessaire. Puisque notre application est extrêmement simple, il nous suffira d'utiliser la mise en page par défaut - default.vue.



De plus, Nuxt utilise une mise en page distincte pour une page d'erreur telle que 404, qui est en fait une page simple.



Dispositions dans le référentiel .



default.vue



Notre default.vue n'aura aucune logique et ressemblera à ceci:



<template lang="pug">  
div  
  nuxt
  db-footer
</template>

      
      





Ici, nous utilisons 2 composants:



1. nuxt - lors de l'assemblage, il sera remplacé par une page spécifique demandée par l'utilisateur.



2.db-footer est notre propre composant Footer (nous l'écrirons un peu plus tard) qui sera automatiquement ajouté à chaque page de notre application.



error.vue



Par défaut, pour toute erreur renvoyée par le serveur dans l'état http, Nuxt redirige vers layout / error.vue et passe un objet contenant une description de l'erreur reçue via un paramètre d'entrée appelé error.



Voyons à quoi ressemble la section de script, ce qui aidera à unifier le travail avec les erreurs reçues:



<script lang="ts">  
import Vue from 'vue'  
  
type Error = {  
  statusCode: number  
  message: string  
}  
  
type ErrorText = {  
  title: string  
  subtitle: string  
}  
  
type ErrorTexts = {  
  [key: number]: ErrorText  
  default: ErrorText  
}  

export default Vue.extend({  
  name: 'ErrorPage',  
  
  props: {  
    error: {  
      type: Object as () => Error,  
      required: true,  
    },  
  },  
  
  data: () => ({  
    texts: {  
      404: {  
        title: '404. Page not found',  
        subtitle: 'Something went wrong, no such address exists',  
      },  
      default: {  
        title: 'Unknown error',  
        subtitle: 'Something went wrong, but we`ll try to figure out what`s wrong',  
      },  
    } as ErrorTexts,  
  }),  

  computed: {  
    errorText(): ErrorText {  
      const { statusCode } = this.error  
      return this.texts[statusCode] || this.texts.default  
    },  
  },  
})  
</script>
      
      





Que se passe-t-il ici:



1. Tout d'abord, nous définissons les types qui seront utilisés dans ce fichier.



2. Dans l'objet de données, nous créons un dictionnaire qui contiendra des messages pour toutes les erreurs pour lesquelles nous voulons afficher un message unique et un message par défaut pour toutes les autres.



3. Dans la propriété calculée errorText, nous vérifions si l'erreur reçue est dans le dictionnaire. S'il y a une erreur, nous renvoyons un message pour cela. S'il n'y a pas d'erreur, renvoyez le message par défaut.



Dans ce cas, notre modèle ressemblera à ceci:



<template lang="pug">  
section.section  
  .content  
    .ep__container  
      section-header(  
        :title="errorText.title"  
        :subtitle="errorText.subtitle"  
      )  

      nuxt-link.ep__link(  
        class="primary"  
        to="/"  
      ) Home page  
</template>
      
      





Notez qu'ici, nous utilisons les classes d'utilitaires globales .section et .content que nous avons créées précédemment dans le fichier assets / styles / global / other.scss. Ils permettent d'afficher le contenu centré sur la page.



Cela utilise le composant d'en-tête de section, qui n'a pas encore été créé, mais à l'avenir, ce sera un composant universel pour afficher les en-têtes. Nous le mettrons en œuvre lorsque nous parlerons de composants.



Le répertoire des mises en page ressemble à ceci: Commençons par créer les composants.



layouts/

-- default.vue

-- error.vue












Composants



Les composants sont les éléments de base de notre application. Commençons par les composants que nous avons déjà vus ci-dessus.



Afin de ne pas gonfler l'article, je ne décrirai pas les styles des composants. Ils peuvent être trouvés dans le référentiel de cette application.



SectionHeader Les

titres de notre application sont créés dans le même style, il est donc logique d'utiliser un composant pour les afficher et modifier les données affichées via les paramètres d'entrée.



Jetons un coup d'œil à la section script de ce composant:



<script lang="ts">  
import Vue from 'vue'  

export default Vue.extend({  
  name: 'SectionHeader',  

  props: {  
    title: {  
      type: String,  
      required: true,  
    },  
    subtitle: {  
      type: String,  
      default: '',  
    },  
  },  
})  
</script>
      
      





Voyons maintenant à quoi ressemblera le modèle:



<template lang="pug">  
section.section  
  .content  
    h1.sh__title(  
      class="h1"  
    ) {{ title }}  

    p.sh__subtitle(  
      v-if="subtitle"  
      class="body2 regular"  
    ) {{ subtitle }}  
</template>
      
      





Comme nous pouvons le voir, ce composant est un simple wrapper pour les données affichées et ne contient aucune logique.



LinkToHome



Le composant le plus simple de notre application est le lien au-dessus du titre qui mène à la page d'accueil de la page de publication sélectionnée.



Ce composant est très petit, je vais donc donner tout son code à la fois (sans styles):



<template lang="pug">  
section.section  
  .content  
    nuxt-link.lth__link(  
      to="/"  
      class="primary"  
    )  
      img.lth__link-icon(  
        src="~/assets/icons/home.svg"  
        alt="icon-home"  
      )  
      | Home  
</template>  
  
<script lang="ts">  
import Vue from 'vue'  

export default Vue.extend({  
  name: 'LinkToHome',  
})  
</script> 
      
      





Notez que nous demandons l'icône home.svg dans le répertoire assets / icons. Tout d'abord, vous devez créer ce répertoire et y ajouter l'icône souhaitée.



DbFooter



Le composant DbFooter est très simple. Il contient des droits d'auteur et un lien pour créer une lettre.

Les exigences sont claires, commençons l'implémentation avec la section script:



<script lang="ts">  
import Vue from 'vue'  

export default Vue.extend({  
  name: 'DbFooter',  

  computed: {  
    copyright(): string {
      const year = new Date().getUTCFullYear()
      return ` ${year} · All rights reserved`
    },  
  },  
})  
</script>
      
      





Dans DbFooter, nous n'avons qu'une seule propriété calculée qui renvoie l'année en cours, concaténée avec une chaîne donnée. Jetons maintenant un œil au modèle:



<template lang="pug">  
section.section  
  .content  
    .footer  
      a.secondary(
        href="mailto:example@mail.com?subject=Nuxt blog"
      ) Contact us  
      p.footer__copyright(
        class="body3 regular"
      ) {{ copyright }}  
</template>
      
      





Lorsque vous cliquez sur le lien Contactez-nous, nous ouvrirons le client de messagerie natif et définirons immédiatement l'objet du message. Cette solution convient pour une démo de notre application, mais dans la vraie vie, une solution plus appropriée serait de mettre en place un formulaire de feedback pour envoyer des messages directement depuis le site. Carte



postale



La carte postale est simple et directe.



<script lang="ts">  
import Vue from 'vue'  
import { Post } from '~/content/Post'  

export default Vue.extend({  
  name: 'PostCard',  

  props: {  
    post: {  
      type: Object as () => Post,  
      required: true,  
    },  
  },  

  computed: {  
    pageUrl(): string {  
      return `/post/${this.post.id}`  
    },  
  },  
})  
</script>
      
      





Dans la section script, nous définissons un paramètre d'entrée, post, qui contiendra toutes les informations nécessaires sur le post.



Nous implémentons également la propriété pageUrl calculée pour une utilisation dans le modèle, qui nous renverra un lien vers la page souhaitée avec l'article.



Le modèle ressemblera à ceci:



<template lang="pug">  
nuxt-link.pc(:to="pageUrl")  
  img.pc__img(  
    :src="getDynamicFile(post.img)"  
    :alt="`post-image-${post.id}`"  
  )  

  p.pc__title(class="body1 medium") {{ post.title }}  
  p.pc__subtitle(class="body3 regular") {{ post.desc }}  
</template>
      
      





Notez que l'élément racine du modèle est nuxt-link. Ceci est fait pour que l'utilisateur ait la possibilité d'ouvrir l'article dans une nouvelle fenêtre à l'aide de la souris.



C'est la première fois que le mixin global getDynamicFile que nous avons créé plus tôt dans cet article est utilisé.



PostList



Le composant principal de la page principale comprendra un compteur de publications en haut et une liste des publications elles-mêmes.



La section script pour ce composant:



<script lang="ts">  
import Vue from 'vue'  
import posts from '~/content/posts'  

export default Vue.extend({  
  name: 'PostList',  
  
  data: () => ({  
    posts,  
  }),  
})  
</script>
      
      





Notez qu'après avoir importé le tableau avec les publications, nous les ajoutons à l'objet de données afin que le modèle ait accès à ces données à l'avenir.



Le modèle lui-même ressemble à ceci:



<template lang="pug">  
section.section  
  .content  
    p.pl__count(class="body2 regular")  
      img.pl__count-icon(  
        src="~/assets/icons/list.svg"  
        alt="icon-list"  
      )  
      | Total {{ posts.length }} posts  

    .pl__items  
      post-card(  
        v-for="post in posts"  
        :key="post.id"  
        :post="post"  
      )  
</template>
      
      





Pour que tout fonctionne correctement, n'oubliez pas d'ajouter l'icône list.svg au répertoire assets / icons.



PostFull



PostFull est le composant principal sur une page de publication distincte qui sera responsable de l'affichage du texte de l'article.



Pour ce composant, nous avons besoin du module @ nuxtjs / markdownit , qui sera responsable de la conversion de md en html.



Installons-le:



npm i @nuxtjs/markdownit
      
      





Ajoutez ensuite @ nuxtjs / markdownit à la section modules du fichier nuxt.config.js:



{
  modules:  [
    '@nuxtjs/markdownit',
  ],
}
      
      





Bien! Commençons par implémenter le composant. Comme toujours, dans la section script:



<script lang="ts">  
import Vue from 'vue'  
import { Post } from '~/content/Post'  
  
export default Vue.extend({  
  name: 'PostFull',  
  
  props: {  
    post: {  
      type: Object as () => Post,  
      required: true,  
    },  
  },  
})  
</script>
      
      





Dans la section script, nous définissons un paramètre d'entrée, post, qui contiendra toutes les informations nécessaires sur le post.



Passons au modèle:



<template lang="pug">  
section.section  
  .content  
    img.pf__image(  
      :src="getDynamicFile(post.img)"  
      :alt="`post-image-${post.id}`"  
    )  

    .pf__md(v-html="getDynamicFile(post.file).default")  
</template>
      
      





Comme vous pouvez le voir, nous obtenons et rendons dynamiquement une image et un fichier .md en utilisant notre mixin getDynamicFile.



Je pense que vous avez remarqué que nous utilisons l'attribut standard v-html pour rendre le fichier, puisque @ nuxtjs / markdownit fera le reste du travail pour nous. Incroyablement simple!



Nous pouvons utiliser le sélecteur :: v-deep pour accéder à la personnalisation du style de notre fichier .md rendu. Jetez un œil sur Github pour voir comment ce composant est implémenté.



Dans ce composant, je ne mets que des retraits pour les paragraphes pour montrer le principe de personnalisation, mais dans une application réelle, vous devrez créer un ensemble complet de styles pour tous les éléments html utilisés et nécessaires.



Des pages



Lorsque tous les composants sont prêts, nous pouvons commencer à créer les pages.



Comme vous l'avez probablement déjà compris à partir de la conception, notre application se composera d'une page principale avec une liste de tous les articles et une page dynamique qui affiche l'article sélectionné.



La structure du répertoire des pages: Tous les composants sont autonomes, et leurs états sont déterminés par des paramètres d'entrée, donc nos pages ressembleront à une liste de composants spécifiés dans l'ordre requis. La page principale ressemblera à ceci:



pages/

-- index.vue

-- post/

---- _id.vue














<template lang="pug">  
.page  
  section-header(  
    title="Nuxt blog"  
    subtitle="The best blog you can find on the global internet"  
  )  

  post-list  
</template>  
  
<script lang="ts">  
import Vue from 'vue'  

export default Vue.extend({  
  name: 'HomePage',  
})  
</script>
      
      





Pour définir le remplissage correct, nous avons utilisé la classe globale .page que nous avons créée précédemment dans assets / styles / global / other.scss.



Une seule page d'article aura l'air un peu plus complexe. Jetons d'abord un coup d'œil à la section script:



<script lang="ts">  
import Vue from 'vue'  
import { Post } from '~/content/Post'  
import posts from '~/content/posts'

export default Vue.extend({  
  validate({ params }) {  
    return /^\d+$/.test(params.id)  
  },  
  
  computed: {  
    currentId(): number {  
      return Number(this.$route.params.id)  
    },  
    currentPost(): Post | undefined {  
      return posts.find(({ id }) => id === this.currentId)  
    },  
  },  
})  
</script>
      
      





Nous voyons la méthode validate. Cette méthode est absente de Vue, Nuxt nous la fournit pour valider les paramètres reçus du routeur. Valider sera appelé à chaque fois que vous naviguerez vers un nouvel itinéraire. Dans ce cas, nous vérifions simplement que l'identifiant qui nous est passé est un nombre. Si la validation échoue, l'utilisateur sera renvoyé à la page d'erreur error.vue.



Il y a 2 propriétés calculées implémentées ici. Examinons de plus



près ce qu'ils font: 1. currentId - cette propriété nous renvoie l'ID de publication actuel (qui a été obtenu à partir des paramètres du routeur), après l'avoir converti en nombre.



2. currentPost renvoie un objet contenant des informations sur le message sélectionné dans le tableau général de tous les articles.



Il semble qu'ils l'ont compris. Jetons un coup d'œil au modèle:



<template lang="pug">  
.page
  link-to-home  

  section-header(  
    :title="currentPost.title"  
  )  

  post-full(  
    :post="currentPost"  
  )
</template>
      
      





La section de style pour cette page, ainsi que pour la page principale, est manquante.

Le code des pages sur Github .



Déployer sur Hostman



Hourra! Notre application est presque prête. Il est temps de commencer à le déployer.



Pour cette tâche, j'utiliserai la plateforme cloud Hostman , qui vous permet d'automatiser le processus de déploiement.



Notre application sera un site statique, puisqu'un plan gratuit est disponible pour les sites statiques dans Hostman.



Pour publier, nous devons cliquer sur le bouton Créer dans l'interface de la plateforme, sélectionner un plan gratuit et connecter notre référentiel Github, en spécifiant les options nécessaires au déploiement.



Immédiatement après cela, la publication démarrera automatiquement et un domaine gratuit sera créé dans la zone * .hostman.site avec le certificat ssl de Let's Encrypt installé.



Désormais, chaque nouveau push vers la branche sélectionnée (maître par défaut) sera utilisé pour déployer une nouvelle version de l'application. Incroyablement simple et pratique!



Conclusion



Donc ce que nous avons:





Nous avons essayé de montrer en pratique comment travailler avec le framework Nuxt.js. Nous avons réussi à créer une application simple du début à la fin, de la création d'un kit d'interface utilisateur à l'organisation d'un déploiement.



Si vous avez suivi toutes les étapes de cet article, félicitations pour la création de votre première application Nuxt.js. Était-ce difficile? Comment travaillez-vous avec ce framework? Si vous avez des questions ou des demandes, n'hésitez pas à nous écrire dans les commentaires.



All Articles