Aplicación Nuxt.js desde el kit de interfaz de usuario hasta la implementación

¡Hola, Habr!



Escribí este tutorial detallado paso a paso para que cualquiera pueda crear su propia aplicación usando el marco Nuxt.js desde cero.



En este artículo, discutiremos los conceptos básicos, los conceptos básicos de la creación de una aplicación Nuxt.js:



  • creación y configuración de proyectos,
  • activos y estáticos: estilos, fuentes, imágenes, publicaciones,
  • creando componentes,
  • creando páginas y diseños,
  • implementación de aplicaciones (implementación).


¡Mira lo que pasó!



Un poco sobre Nuxt.js



Nuxt es un marco Vue de alto nivel. Nuxt.js le permite desarrollar aplicaciones web isomórficas listas para usar al abstraer los detalles de distribución del código del servidor y del cliente. Gracias a este enfoque, ahorramos tiempo y podemos centrarnos en el desarrollo.



Las principales ventajas de Nuxt:



  • SPA, SSR y preprocesamiento ya están configurados; todo lo que se requiere de nosotros es indicar. En esta aplicación, usamos un renderizado previo para el modo de producto, es decir, generaremos todas las páginas del sitio por adelantado y luego las implementaremos en el alojamiento para distribuir estáticas.
  • Un gran SEO para todos los motores de búsqueda es el resultado del uso de SSR o pre-renderizador.
  • . js chunks, css styles API ( webpack 4, Nuxt).
  • Google Lighthouse / Page Speed. 100/100 .
  • CSS Modules, Babel, Postscc create-nuxt-app.
  • .
  • 50 Vue.js.


Podemos hablar de los beneficios de Nuxt durante mucho tiempo. Este es el marco que realmente amo por su facilidad de uso y la capacidad de crear aplicaciones flexibles y fácilmente escalables. Entonces, propongo comenzar y ver todos los beneficios en la práctica.

Más información sobre Nuxt.js en el sitio oficial . Las guías detalladas también están disponibles aquí .



Diseño



Un diseño bien pensado y listo para usar, o mejor aún, un kit de interfaz de usuario, acelerará y simplificará significativamente el desarrollo de cualquier aplicación. Si no hay un diseñador de interfaz de usuario gratuito cerca, está bien. Como parte de nuestras instrucciones, ¡podemos manejarlo nosotros mismos!



Especialmente para este artículo, preparé un diseño de blog en un estilo moderno y minimalista con una funcionalidad simple, suficiente para demostrar las capacidades de Nuxt.



Para el desarrollo, utilicé el servicio en línea Figma. El diseño y el kit de interfaz de usuario están disponibles aquí . Puede copiar esta plantilla y utilizarla en su proyecto.



Creación de proyectos



Para crear un proyecto, usaremos la utilidad Nuxt create-nuxt-app de los desarrolladores de Nuxt , que nos permite configurar la plantilla de la aplicación a través del cli.



Inicializamos el proyecto especificando su nombre:



npx create-nuxt-app nuxt-blog
      
      





Además, en varias etapas, la utilidad nos ofrecerá elegir un conjunto de bibliotecas y paquetes preferidos, después de lo cual los descargará, configurará y configurará de forma independiente para el proyecto.



Puede ver una lista completa de las opciones seleccionadas en Github .



Para este proyecto se utilizará la configuración con TypeScript.



Al desarrollar en Vue con Typescript, puede usar dos API: API de opciones o API de clase .



No difieren funcionalmente entre sí, pero tienen una sintaxis diferente. Personalmente, la sintaxis de la API de Opciones está más cerca de mí, por lo que será utilizada en nuestro proyecto.



Después de crear el proyecto, podemos ejecutar nuestra aplicación usando el comando: npm run dev. Ahora estará disponible en localhost: 3000.



Nuxt usa webpack-dev-server con HMR instalado y configurado como servidor local , lo que hace que el desarrollo sea rápido y cómodo.



Dado que estamos creando una versión de demostración de la aplicación, no escribiré pruebas para ella. Pero recomiendo encarecidamente no descuidar las pruebas de aplicaciones en el desarrollo comercial.



Si no ha tocado este tema antes, le aconsejo que preste atención a Jest , una herramienta muy simple, pero al mismo tiempo poderosa, que permite trabajar con Nuxt junto con vue-test-utils .



Estructura del proyecto



Nuxt crea de forma predeterminada un directorio y una estructura de archivos adecuados para un inicio rápido del desarrollo. Para nuestro proyecto, dicha estructura se adapta perfectamente, por lo que no la cambiaremos. Puede leer más sobre el propósito de los diferentes directorios en el sitio web de Nuxt .



-- Assets

-- Static

-- Pages

-- Middleware

-- Components

-- Layouts

-- Plugins

-- Store

-- nuxt.config.js

-- ...other files














Creación de aplicaciones



Antes de escribir el código, hagamos lo siguiente:



1. Elimine los componentes de inicio y las páginas generadas por Nuxt.

2. Instale pug y scss para nuestra conveniencia y para ahorrar tiempo durante el desarrollo. Ejecutemos el comando:



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





Después de eso, el uso del atributo lang para la plantilla y las etiquetas de estilo estará disponible:



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

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





3. Agregue soporte para el selector :: v-deep deep a la configuración stylelint, lo que permitirá aplicar estilos a los componentes secundarios, ignorando el ámbito. Puede leer más sobre este selector aquí.



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





Todos los preparativos han terminado, pase a la siguiente etapa.



Publicaciones



Las publicaciones se almacenarán en el directorio de contenido / publicaciones, que crearemos en la raíz del proyecto como un conjunto de archivos de rebajas.



Creemos 5 archivos pequeños para que podamos empezar a trabajar con ellos de inmediato. Para simplificar, usaremos los nombres 1.md, 2.md, etc.



En el directorio de contenido, crearemos el archivo Posts.d.ts, en el que definimos los tipos para el objeto que contiene toda la información necesaria sobre la publicación:



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





Creo que el significado de todos los campos debería quedar claro en los nombres.



Siga adelante. En el mismo directorio, cree otro archivo llamado posts.ts con el siguiente contenido:



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[]
      
      





En la propiedad img, nos referimos a las imágenes en el directorio assets / images, pero aún no hemos creado este directorio, hagámoslo ahora.



Ahora agreguemos las imágenes en formato .svg al directorio creado con los nombres que especificamos anteriormente.



Tomaré 5 imágenes de unDraw . Este excelente recurso se actualiza constantemente y contiene muchas imágenes svg gratuitas.



Ahora que todo está listo, el directorio de contenido debería verse así: Y el subdirectorio de imágenes debería aparecer en el directorio de activos con el siguiente contenido:



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

...








Recuperar archivos dinámicamente



Dado que recibiremos imágenes y archivos con el texto de las publicaciones de forma dinámica, necesitamos implementar un mixin global, que podemos usar más en todos los componentes.



Para hacer esto, cree un subdirectorio mixins en el directorio de complementos, y en él un archivo getDynamicFile.ts con el siguiente contenido:



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





Todo lo que nos queda es habilitar este mixin en el archivo nuxt.config.js:



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





Fuentes



Después de la etapa de creación de publicaciones, conecte las fuentes. La forma más sencilla de hacer esto es la maravillosa biblioteca Webfontloader , que le permite obtener cualquier fuente de Google Fonts . Sin embargo, en el desarrollo comercial, a menudo se usan fuentes personalizadas, así que veamos solo ese caso aquí.



Se eligió Rubik como fuente para nuestra aplicación, que se distribuye bajo la Open Font License . Puede descargarlo todo desde las mismas fuentes de Google .



Tenga en cuenta que en el archivo descargado las fuentes estarán en formato otf, pero dado que trabajamos con la web, los formatos woff y woff2 serán la mejor opción para nosotros. Son más pequeños que cualquier otro formato, pero son perfectamente compatibles con todos los navegadores modernos. Para convertir otf a los formatos que necesitamos, puede utilizar uno de los muchos servicios gratuitos en línea.



Entonces, tenemos las fuentes en los formatos que necesitamos, es hora de incluirlas en el proyecto. Para hacer esto, cree un subdirectorio de fuentes en el directorio estático y agregue nuestras fuentes allí. Creemos un archivo fonts.css en el mismo directorio, que se encargará de conectar nuestras tipografías en la aplicación con el siguiente contenido:



@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");  
}  
  
...
      
      





El contenido completo del archivo se puede ver en el repositorio .



Hay 2 cosas que vale la pena notar:



1. Especificamos font-display: swap;, definiendo cómo se mostrará la fuente conectada a través de font-face dependiendo de si está cargada y lista para usar.

En este caso, no establecemos el período de bloqueo y establecemos un período de sustitución infinito. Es decir, la carga de la fuente se produce en segundo plano y no bloquea la carga de la página, y la fuente se mostrará cuando esté lista.



2. En src, especificamos el orden de arranque por prioridad. Primero, verificamos si la fuente deseada está instalada en el dispositivo del usuario verificando las posibles variantes del nombre de la fuente. Si no lo encontramos, entonces verificamos si el navegador es compatible con el formato woff2 más moderno, y si no, pasamos al siguiente formato woff. Existe la posibilidad de que el usuario esté usando un navegador desactualizado (por ejemplo, IE <9), en este caso, en lo que sigue, indicaremos las fuentes integradas en el navegador como respaldo.



Después de crear el archivo con las reglas de carga de fuentes, debe conectarlo en la aplicación, en el archivo nuxt.config.js en la sección principal:



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





Tenga en cuenta que aquí, como antes, estamos utilizando las propiedades de precarga y precarga, por lo que establecemos una alta prioridad en el navegador para descargar estos archivos y no bloqueamos la representación de la página.



Agreguemos inmediatamente al directorio de favoritos estático de nuestra aplicación, que se puede generar utilizando cualquier servicio en línea gratuito.



El directorio estático ahora tiene este aspecto: continúe con el siguiente paso.



static/

-- fonts/

---- fonts.css

---- Rubik-Bold.woff2

---- Rubik-Bold.woff

---- Rubik-Medium.woff2

---- Rubik-Medium.woff

---- Rubik-Regular.woff2

---- Rubik-Regular.woff

-- favicon.ico












Estilos reutilizables



En nuestro proyecto, todos los estilos utilizados se describen mediante un único conjunto de reglas, lo que facilita mucho el desarrollo, así que transfiramos estos estilos de Figma a los archivos del proyecto.

En el directorio de activos, cree un subdirectorio de estilos, en el que almacenaremos todos los estilos reutilizados en el proyecto. A su vez, el directorio de estilos contendrá el archivo variables.scss con todas nuestras variables scss.



El contenido del archivo se puede ver en el repositorio .



Ahora necesitamos conectar estas variables al proyecto para que estén disponibles en cualquiera de nuestros componentes. Nuxt usa el módulo @ nuxtjs / style-resources para este propósito .



Instalemos este módulo:



npm i @nuxtjs/style-resources
      
      





Y agregue las siguientes líneas a nuxt.config.js:



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

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





¡Multa! Las variables de este archivo estarán disponibles en cualquier componente.



El siguiente paso es crear algunas clases auxiliares y estilos globales que se utilizarán en toda la aplicación. Este enfoque le permitirá administrar de forma centralizada estilos comunes y adaptar rápidamente la aplicación si el diseñador cambia la apariencia de los diseños.



Creemos un subdirectorio global en el directorio assets / styles con los siguientes archivos:



1. typography.scss: el archivo contendrá todas las clases auxiliares para el texto, incluidos los enlaces.

Tenga en cuenta que estas clases de ayuda cambian de estilo según la resolución del dispositivo del usuario: teléfono inteligente o PC.



2. transitions.scss: el archivo contendrá estilos de animación globales, tanto para las transiciones entre páginas como para las animaciones dentro de los componentes, si lo necesitamos en el futuro.



3. other.scss: el archivo contendrá estilos globales, que aún no se han seleccionado en un grupo separado.



La clase .page se utilizará como un contenedor común para todos los componentes de la página y formará el relleno correcto en la página.



La clase .section se utilizará para marcar los límites de los cuadros lógicos, y la clase .content se utilizará para restringir el ancho del contenido y centrarlo en la página.



Veremos ejemplos de cómo se usan estas clases más adelante cuando comencemos a implementar componentes y páginas.



4. index.scss: un archivo general que se utilizará como un único punto de exportación para todos los estilos globales.



El contenido completo de los archivos se puede ver en Github .



En esta etapa, incluiremos estos estilos globales para que estén disponibles en toda la aplicación. Para esta tarea, Nuxt nos proporciona una sección css en el archivo nuxt.config.js:



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





Vale la pena decir que en el futuro, al asignar clases-CSS, se utilizará la siguiente lógica:



1. Si una etiqueta tiene clases auxiliares y clases locales, las clases locales se agregarán directamente a la etiqueta, por ejemplo, p .some-local-class, y las clases auxiliares se especifican en la propiedad de la clase, por ejemplo, class = "body3 medium".



2. Si una etiqueta tiene solo clases auxiliares o solo clases locales, se agregarán directamente a la etiqueta.



Utilizo esta técnica para mi conveniencia, para distinguir visualmente de inmediato entre clases globales y locales.



Antes del desarrollo, instalemos y habilitemos reset.css para que nuestro diseño se vea igual en todos los navegadores. Para hacer esto, instale el paquete requerido:



npm i reset-css
      
      





Y lo incluiremos en el archivo nuxt.config.js en la sección css ya familiar, que ahora se verá así:



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





¿Sucedió? Si es así, ¡estamos listos para pasar al siguiente paso!



Diseños



En Nuxt, los Layouts son envoltorios sobre páginas que le permiten reutilizar componentes comunes entre ellos e implementar la lógica común necesaria. Dado que nuestra aplicación es extremadamente simple, nos bastará con usar el diseño predeterminado: default.vue.



Además, Nuxt usa un diseño separado para una página de error como 404, que en realidad es una página simple.



Diseños en el repositorio .



default.vue



Nuestro default.vue no tendrá lógica y se verá así:



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

      
      





Aquí usamos 2 componentes:



1. nuxt - durante el ensamblaje, será reemplazado por una página específica solicitada por el usuario.



2.db-footer es nuestro propio componente Footer (lo escribiremos un poco más adelante) que se agregará automáticamente a cada página de nuestra aplicación.



error.vue



De forma predeterminada, para cualquier error devuelto por el servidor en el estado http, Nuxt redirige a layout / error.vue y pasa un objeto que contiene una descripción del error recibido a través de un parámetro de entrada llamado error.



Veamos cómo se ve la sección del script, que ayudará a unificar el trabajo con los errores recibidos:



<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>
      
      





Qué sucede aquí:



1. Primero, definimos los tipos que se usarán en este archivo.



2. En el objeto de datos, creamos un diccionario que contendrá mensajes para todos los errores para los que queremos mostrar un mensaje único y un mensaje predeterminado para todos los demás.



3. En la propiedad calculada errorText, verificamos si el error recibido está en el diccionario. Si hay un error, devolvemos un mensaje. Si no hay ningún error, devuelva el mensaje predeterminado.



En este caso, nuestra plantilla se verá así:



<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>
      
      





Tenga en cuenta que aquí estamos usando las clases de utilidad global .section y .content que creamos anteriormente en el archivo assets / styles / global / other.scss. Permiten que el contenido se muestre centrado en la página.



Esto utiliza el componente de encabezado de sección, que aún no se ha creado, pero en el futuro será un componente universal para mostrar encabezados. Lo implementaremos cuando hablemos de componentes.



El directorio de diseños se ve así: Comencemos a crear los componentes.



layouts/

-- default.vue

-- error.vue












Componentes



Los componentes son los componentes básicos de nuestra aplicación. Comencemos con los componentes que ya hemos visto anteriormente.



Para no inflar el artículo, no describiré los estilos de los componentes. Se pueden encontrar en el repositorio de esta aplicación.



SectionHeader Los

encabezados de nuestra aplicación están hechos con el mismo estilo, por lo que es lógico usar un componente para mostrarlos y cambiar los datos mostrados a través de los parámetros de entrada.



Echemos un vistazo a la sección de script de este componente:



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

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

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





Ahora veamos cómo se verá la plantilla:



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

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





Como podemos ver, este componente es un contenedor simple para los datos mostrados y no contiene ninguna lógica.



LinkToHome



El componente más simple de nuestra aplicación es el enlace sobre el título que conduce a la página de inicio desde la página de publicación seleccionada.



Este componente es muy pequeño, así que daré todo su código a la vez (sin estilos):



<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> 
      
      





Tenga en cuenta que estamos solicitando el icono home.svg del directorio assets / icons. Primero, debe crear este directorio y agregar allí el icono deseado.



DbFooter



El componente DbFooter es muy simple. Contiene derechos de autor y un enlace para crear una carta.

Los requisitos son claros, comencemos la implementación con la sección de 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>
      
      





En DbFooter, solo tenemos una propiedad calculada que devuelve el año actual, concatenado con una cadena determinada. Ahora echemos un vistazo a la plantilla:



<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>
      
      





Cuando haga clic en el enlace Contáctenos, abriremos el cliente de correo nativo e inmediatamente estableceremos el asunto del mensaje. Esta solución es adecuada para una demostración de nuestra aplicación, pero en la vida real, una solución más adecuada sería implementar un formulario de comentarios para enviar mensajes directamente desde el sitio.



Postal



La tarjeta postal es simple y directa.



<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>
      
      





En la sección del script, definimos un parámetro de entrada, publicación, que contendrá toda la información necesaria sobre la publicación.



También implementamos la propiedad pageUrl calculada para usar en la plantilla, que nos devolverá un enlace a la página deseada con la publicación.



La plantilla se verá así:



<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>
      
      





Tenga en cuenta que el elemento raíz de la plantilla es nuxt-link. Esto se hace para que el usuario tenga la oportunidad de abrir la publicación en una nueva ventana usando el mouse.



Esta es la primera vez que se utiliza el mixin getDynamicFile global que creamos anteriormente en este artículo.



PostList



El componente principal de la página principal consistirá en un contador de publicaciones en la parte superior y una lista de las publicaciones en sí.



La sección de secuencia de comandos para este componente:



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

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





Tenga en cuenta que después de importar la matriz con publicaciones, las agregamos al objeto de datos para que la plantilla tenga acceso a estos datos en el futuro.



La plantilla en sí tiene este aspecto:



<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>
      
      





Para que todo funcione correctamente, no olvide agregar el icono list.svg al directorio assets / icons.



PostFull



PostFull es el componente principal en una página de publicación separada que será responsable de mostrar el texto de la publicación.



Para este componente, necesitamos el módulo @ nuxtjs / markdownit , que se encargará de convertir md a html.



Vamos a instalarlo:



npm i @nuxtjs/markdownit
      
      





Luego agregue @ nuxtjs / markdownit a la sección de módulos del archivo nuxt.config.js:



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





¡Multa! Comencemos a implementar el componente. Como siempre, desde la sección de guiones:



<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>
      
      





En la sección del script, definimos un parámetro de entrada, publicación, que contendrá toda la información necesaria sobre la publicación.



Pasando a la plantilla:



<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>
      
      





Como puede ver, obtenemos y renderizamos dinámicamente tanto una imagen como un archivo .md usando nuestro mixin getDynamicFile.



Creo que notó que estamos usando el atributo v-html estándar para renderizar el archivo, ya que @ nuxtjs / markdownit hará el resto del trabajo por nosotros. ¡Increíblemente simple!



Podemos usar el selector :: v-deep para acceder a la personalización de estilo de nuestro archivo .md renderizado. Eche un vistazo a Github para ver cómo se implementa este componente.



En este componente, solo establezco sangrías para los párrafos para mostrar el principio de personalización, pero en una aplicación real, deberá crear un conjunto completo de estilos para todos los elementos html usados ​​y necesarios.



Páginas



Cuando todos los componentes estén listos, podemos empezar a crear las páginas.



Como probablemente ya entendió por el diseño, nuestra aplicación constará de una página principal con una lista de todos los artículos y una página dinámica que muestra la publicación seleccionada.



La estructura del directorio de páginas: Todos los componentes son autónomos y sus estados se determinan mediante parámetros de entrada, por lo que nuestras páginas se verán como una lista de componentes especificados en el orden requerido. La página principal se verá así:



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>
      
      





Para establecer el relleno correcto, usamos la clase .page global que creamos anteriormente en assets / styles / global / other.scss.



Una sola página de publicación se verá un poco más compleja. Primero echemos un vistazo a la sección del guión:



<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>
      
      





Vemos el método de validación. Este método está ausente en Vue, Nuxt nos lo proporciona para validar los parámetros recibidos del enrutador. Se llamará a Validate cada vez que navegue hacia una nueva ruta. En este caso, solo verificamos que la identificación que se nos pasa sea un número. Si la validación falla, el usuario volverá a la página de error error.vue.



Hay 2 propiedades calculadas implementadas aquí. Echemos un



vistazo más de cerca a lo que hacen: 1. currentId - esta propiedad nos devuelve el ID de publicación actual (que se obtuvo de los parámetros del enrutador), habiéndolo convertido previamente en número.



2. currentPost devuelve un objeto con información sobre la publicación seleccionada de la matriz general de todas las publicaciones.



Parece que lo descubrieron. Echemos un vistazo a la plantilla:



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

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

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





Falta la sección de estilo para esta página, así como para la página principal.

El código de las páginas de Github .



Implementar en Hostman



¡Hurra! Nuestra aplicación está casi lista. Es hora de comenzar a implementarlo.



Para esta tarea, utilizaré la plataforma en la nube de Hostman , que le permite automatizar el proceso de implementación.



Nuestra aplicación será un sitio estático, ya que hay un plan gratuito disponible para sitios estáticos en Hostman.



Para publicar debemos hacer clic en el botón Crear en la interfaz de la plataforma, seleccionar un plan gratuito y conectar nuestro repositorio Github, especificando las opciones necesarias para el despliegue.



Inmediatamente después de eso, la publicación comenzará automáticamente y se creará un dominio gratuito en la zona * .hostman.site con el certificado ssl de Let's Encrypt instalado.



A partir de ahora, cada nuevo envío a la rama seleccionada (maestra por defecto) se utilizará para implementar una nueva versión de la aplicación. ¡Increíblemente simple y conveniente!



Conclusión



Entonces, lo que tenemos:





Intentamos mostrar en la práctica cómo trabajar con el marco Nuxt.js. Logramos crear una aplicación simple de principio a fin, desde la creación de un kit de interfaz de usuario hasta la organización de una implementación.



Si ha seguido todos los pasos de este artículo, enhorabuena por crear su primera aplicación Nuxt.js. ¿Fue dificil? ¿Cómo trabaja con este marco? Si tiene alguna pregunta o solicitud, no dude en escribirnos en los comentarios.



All Articles