Aprenda a crear una aplicación Nuxt.

CRUD – Crear, Leer, Actualizar, Eliminar

Asumo que ya conoce los fundamentos de Vue JS y/o está un poco familiarizado con el framework. Nuxt JS es un framework robusto, construido sobre Vue JS. Es esencialmente lo mismo que Vue JS. Entonces, ¿por qué Nuxt?

Para la mayoría de la gente, la decisión de utilizar Nuxt JS suele ser por sus capacidades SSR.

¿Qué es SSR?

SSR es la abreviatura de Server Side Rendering.

Normalmente, para la mayoría de las Aplicaciones de Página Única (SPA), los archivos renderizados se autoinyectan en el DOM después de que la página se haya cargado. Por lo tanto, los bots, rastreadores SEO encontrarán una página vacía en la carga de la página. Sin embargo, para SSR, debido a su capacidad de pre-renderizar las aplicaciones en el servidor antes de la página, esa página puede ser fácilmente indexada por los rastreadores SEO. Además, posiblemente hace que la aplicación tenga un rendimiento superior al de una SPA normal.

Nuxt J S ofrece a los desarrolladores la posibilidad de crear aplicaciones SPA con facilidad. Las aplicaciones Vue JS SPA normales también pueden configurarse para utilizar SSR, pero el proceso es algo engorroso, y Nuxt JS proporciona una envoltura para manejar toda esa configuración. Aparte del SSR, Nuxt también proporciona una manera fácil de configurar su proyecto VueJS con más eficiencia.

Aunque Nuxt JS sigue siendo Vue JS, tiene algunas diferencias fundamentales en cómo se estructura su arquitectura de carpetas.

El objetivo de este artículo es que usted sea capaz de construir una aplicación con Nuxt; por lo tanto, no vamos a profundizar en la arquitectura de carpetas de Nuxt, sin embargo, explicaré rápidamente algunas de las importantes que podríamos necesitar aquí.

Páginas

La carpeta pages es una de las diferencias fundamentales con respecto a Vue SPA regular. Representa la carpeta Views en la arquitectura Vue regular, mores o, en Nuxt, los archivos creados en la carpeta Pages se aprovisionan automáticamente como una ruta. Es decir, cuando crea un archivo index.vue en la carpeta pages, éste se convierte automáticamente en su ruta raíz, es decir, localhost:3000/.

Asimismo, cuando crea cualquier otro archivo index.vue, se convierte en una ruta – crear about.vue le permite acceder a localhost:3000/about.

También puede crear una carpeta dentro de la carpeta Pages. Si crea una carpeta llamada ‘contacto’ y dentro de esa carpeta tiene email.vue, entonces podrá acceder a localhost:3000/contacto/email. Así de sencillo. De esta forma, no necesita crear manualmente un archivo router.js como haría normalmente con Vue JS para crear sus rutas.

Componentes

Sigue siendo prácticamente lo mismo que con Vue JS, los componentes creados no se aprovisionan automáticamente como rutas.

Estática

La carpeta estática sustituye a la carpeta pública en las aplicaciones Vue JS normales, funciona prácticamente igual. Los archivos aquí no se compilan, se sirven de la misma forma que se almacenan.

Puede leer todo sobre la arquitectura y estructura en la página de documentación de Nuxt JS.

Ahora, vamos a construir algo interesante…

Construir una aplicación de tienda de libros

Vamos a construir una app de tienda de libros, en la que un usuario pueda añadir los libros que ha leído a una categoría concreta que le guste. Tendrá este aspecto.

Así, tendremos un diseño simple como el anterior, sólo 3 columnas que contienen las diferentes secciones de libros. Libros leídos recientemente, libros favoritos, y sí, lo mejor de los mejores libros (voy a confesar, no sabía cómo llamar a esa sección, 🙂 )

Así que el objetivo aquí, es poder añadir el título, autor y descripción de un libro a una ficha en cualquiera de las secciones, editar libros ya añadidos y eliminar un libro existente. No vamos a utilizar ninguna base de datos, por lo que todo sucede en el estado.

En primer lugar, instalamos Nuxt:

npm install create-nuxt-app

En segundo lugar, después de instalar Nuxt, ya puede crear el proyecto con el comando

create-nuxt-app bookStore

He elegido llamar a mi aplicación ‘bookStore’; usted puede llamar a su algo más fresco ^_^

A continuación, vamos a recorrer las indicaciones restantes, introduzca una descripción,

Nombre del autor, escriba un nombre o pulse intro para conservar los valores predeterminados

Seleccione un gestor de paquetes, cualquiera con el que se sienta cómodo, ambos están bien

Seleccione un framework de interfaz de usuario. Para este proyecto, voy a utilizar Vuetify, pero de nuevo, cualquier marco de interfaz de usuario con el que se sienta cómodo estará bien.

Seleccione un framework de servidor personalizado; no necesitamos ninguno, seleccionaré ninguno

Módulos extra, seleccione lo que quiera, o seleccione ambos, no los usaremos para esta aplicación.

Linting es importante. Vamos con ESLint.

Aunque las pruebas son importantes, hoy no vamos a ocuparnos de eso, así que ninguna

Modo de renderizado, sí es SSR.

Nota: Elegir SSR no significa que no obtengamos el beneficio de tener una SPA, la aplicación sigue siendo una SPA pero con SSR. La otra opción significa simplemente SPA y sin SSR.

Pulse enter y siga adelante,

Y nuestro proyecto se está creando,

Después de la creación, ahora podemos entrar en el directorio y ejecutar

yarn dev

si está utilizando npm como gestor de paquetes, utilice

npm run dev

Por defecto, la aplicación se ejecuta en localhost:3000. Visite el enlace en su navegador, y debería ver una página Nuxt por defecto.

Comencemos ahora con la creación de los componentes que necesitamos. Tendremos tarjetas que muestren la información de cada libro, y tendremos un modal que contenga un formulario para introducir nueva información del libro o editar la existente.

Para crear un componente, simplemente cree un nuevo archivo en la carpeta components. Aquí está el código para mi componente de tarjeta.

// BookCard.vue


  
    
    {{bookTitle}}
    {{bookAuthor}}
    {{Descripcióndellibro}}
    
      
      
    
  


<script>
export default {
  props: ["bookTitle", "bookAuthor", "bookDescription"]
};
</script>

Una explicación rápida de lo que se hace arriba. La imagen está codificada; no nos preocuparemos de eso por ahora. El título del libro, el autor del libro y la descripción del libro se pasan a este componente desde la página padre como props. Si no está familiarizado con los props, imagínelos como puntos de entrada a través de los cuales este componente puede ser poblado con datos.

Ahora pasemos al siguiente componente, el modal.

//BookModal.vue


  
    
      Añadir libros
      
        
        
        
        
      
      
        
        Añadir
      
    
  

Ahora, ese es el marcado para el modal; necesitamos crear los modelos v como propiedades de datos; por lo tanto, añadiremos una etiqueta script debajo de la etiqueta .

<script>
export default {
  data() {
    return {
      category: "",
      título: "",
      autor: "",
      descripción: "",
    };
  },
}
</script>

Además, hay un desplegable ‘Seleccionar una categoría’ que está esperando datos de ‘categorías’. Añadiremos eso a los datos.

<script>
exportar por defecto {
  datos() {
    return {
      abierto: false,
      categoría: "",
      título: "",
      autor: "",
      descripción: "",
      categorías: ["Libros leídos recientemente", "Libros favoritos", "Lo mejor de lo mejor"]
    };
  },
}
</script>

Ahora, necesitamos una manera de alternar entre abrir y cerrar nuestro modal, por ahora, sólo tendremos una propiedad de datos ‘open’ como arriba. Nos fijaremos en eso a continuación.

Vamos a crear rápidamente nuestra página de vista donde tendremos tres cuadrículas/columnas, una para cada sección del libro. Llamemos a la página index.vue, vea el código a continuación.

//index.vue

Libros leídos recientemente

Libros favoritos

Los mejores


Ahora que tenemos nuestras rejillas, necesitamos añadir nuestro componente de tarjeta a cada rejilla, para cada libro añadido. Por lo tanto, importaremos nuestro componente BookCard.vue.

Libros leídos recientemente

Editar Eliminar

Libros favoritos

Editar Eliminar

Lo mejor de lo mejor

Editar Eliminar

Ahora, hemos importado el componente BookCard y hemos vinculado sus props a los resultados del bucle; esto garantiza que por cada entrada añadida a cualquiera de las secciones, se cree una tarjeta para ella. Además, en cada tarjeta incluiremos botones para editarla o eliminarla.

Ahora, necesitamos importar la tarjeta del script y definir las matrices que contendrán los registros de cada una de las categorías.

<script>
import BookCard from "@/components/BookCard";

exportar por defecto {
  componentes: {
    BookCard,
  },
  datos() {
    devolver {
      librosrecientes [],
      librosfavoritos: [],
      mejoresDeLosMejores: []
    };
  },
};
</script>

A continuación, necesitamos tener un botón en la cabecera que abra el modal cada vez que necesitemos añadir libros. Haremos esto en el archivo ‘default.vue’. Añadiremos el botón a la cabecera de la barra de aplicaciones por defecto.

Añadir Libros

A continuación, necesitamos crear el método openModal en la sección script. En las aplicaciones Vue JS normales, existe un bus de eventos que le permite comunicarse con otro componente e incluso pasar datos entre ellos, en Nuxt JS, sigue existiendo un bus de eventos y puede seguir creándolo de la misma forma. Así pues, utilizaremos un bus de eventos para pasar datos abrir un modal en la página index.vue (que aún debemos importar) desde el archivo layout/default.vue.

Veamos cómo se hace.

Para crear un bus de eventos global, abra un archivo en el directorio raíz del proyecto, nómbrelo eventBus.js y pegue en él el código que aparece a continuación.

import Vue from 'vue'

export const eventBus = new Vue()

Sí, eso es todo. Ahora podemos usarlo.

<script>
import { eventBus } from "@/eventBus";
métodos: {
    abrirModal() {
      eventBus.$emit("abrir-añadir-libro-modal");
    }
  }
</script>

A continuación, volveremos a nuestro componente BookModal, y escucharemos cuando el eventBus emita ‘open-add-book-modal’. Añadiremos esto a la sección script.

import { eventBus } from "@/eventBus";

creado() {
    eventBus.$on("abrir-añadir-libro-modal", this.open = true);
  },

Ahora podemos abrir y cerrar nuestro modal, pero aún no añade ningún libro. Añadamos un método a nuestro modal para hacer que guarde lo que se añade al estado (recuerde que no estamos haciendo uso de ninguna base de datos o almacenamiento local). Añadimos esto junto a ‘created()

métodos: {
    saveBook() {
      let cardData = {
        título: this.title
        autor: this.author
        descripción: this.description
        categoría: this.category
      };
      eventBus.$emit("guardar-libro", cardData);
      this.open = false;
    }
  }

A continuación, necesitamos una forma de volver a rellenar el modal cuando estemos editando datos de cualquiera de las tarjetas. Así que hagamos algunos ajustes en la función ‘created()

creado() {
    eventBus.$on("abrir-añadir-libro-modal", datos => {
      if (datos) {
        this.category = data.category
        this.title = data.title
        this.author = data.author
        this.description = data.description;
      }
      this.open = true;
    });
  },

Ahora, el BookModal tiene este aspecto en su conjunto,

//BookModal.vue



  
    
      Añadir libros
      
        
        
        
        
      
      
        
        Añadir
      
    
  


<script>
import { eventBus } from "@/eventBus";
exportar por defecto {
  datos() {
    return {
      abierto: false
      categoría: "",
      título: "",
      autor: "",
      descripción: "",
      categorías: ["Libros leídos recientemente", "Libros favoritos", "Lo mejor de lo mejor"]
    };
  },
  creado() {
    eventBus.$on("abrir-añadir-libro-modal", datos => {
      if (datos) {
        this.category = data.category
        this.title = data.title
        this.author = data.author
        this.description = data.description;
      }
      this.open = true;
    });
  },
  métodos: {
    guardarLibro() {
      let cardData = {
        título: this.title
        autor: this.author
        descripción: this.description
        categoría: this.category
      };
      eventBus.$emit("guardar-libro", cardData);
      this.open = false;
    }
  }
};
</script>

A continuación, podemos volver a la página index.vue para importar el componente BookModal. Añadiremos esto a la sección script.

<script>
import BookCard from "@/components/BookCard";
import BookModal from "@/components/BookModal";
import { eventBus } from "@/eventBus";

exportar por defecto {
  componentes: {
    BookCard,
    BookModal
  },
  datos() {
    devolver {
      librosrecientes [],
      librosfavoritos: [],
      mejoresDeLosMejores: []
    };
  },
</script>

Además, en el cuerpo, añadiremos,

Necesitamos métodos para editar y eliminar una tarjeta. En la plantilla anterior, ya pasé los métodos editar y eliminar a los botones como se muestra a continuación, asimismo, pasé los argumentos necesarios para cada método.

 Editar Eliminar 

Creemos los métodos.

métodos: {
    eliminar(categoría, índice) {
      if (categoría === "Libros leídos recientemente") {
        this.recentBooks.splice(index, 1);
      }
      if (category === "Libros favoritos") {
        this.librosfavoritos.splice(index, 1);
      }
      if (category === "Lo mejor de lo mejor") {
        this.loMejorDeLosMejores.splice(index, 1);
      }
    },
    edit(item, index) {
      if (item.category === "Libros leídos recientemente") {
        eventBus.$emit("abrir-añadir-libro-modal", item);
        this.recentBooks.splice(index, 1);
      }
      if (item.category === "Libros favoritos") {
        eventBus.$emit("abrir-añadir-libro-modal", item);
        this.librosfavoritos.splice(index, 1);
      }
      if (item.category === "Lo mejor de lo mejor") {
        eventBus.$emit("abrir-añadir-libro-modal", item);
        this.loMejorDeLosMejores.splice(index, 1);
      }
    }
  }

Recuerde, el BookModal está emitiendo, y un evento llamado guardar-libro, necesitamos un oyente para ese evento aquí.

creado() {
    eventBus.$on("guardar-libro", cardData => {
      if (cardData.category === "Libros leídos recientemente") {
        this.recentBooks.push(cardData);
      }
      if (cardData.category === "Libros favoritos") {
        this.favouriteBooks.push(cardData);
      }
      if (cardData.category === "Lo mejor de lo mejor") {
        this.loMejorDeLosMejores.push(cardData);
      }
    });
  },

Ahora, de un solo vistazo, nuestra página index.vue tiene el siguiente aspecto

Libros leídos recientemente

Ver Editar Eliminar

Libros favoritos

Editar Eliminar

Lo mejor de lo mejor

Editar Eliminar



<script>
import BookCard from "@/components/BookCard";
import BookModal from "@/components/BookModal";
import { eventBus } from "@/eventBus";

exportar por defecto {
  componentes: {
    BookCard,
    BookModal
  },
  datos() {
    devolver {
      librosrecientes [],
      librosfavoritos: [],
      mejoresDeLosMejores: []
    };
  },
  creado() {
    eventBus.$on("guardar-libro", cardData => {
      if (cardData.category === "Libros leídos recientemente") {
        this.recentBooks.push(cardData);
        this.recentBooks.sort((a, b) => b - a);
      }
      if (cardData.category === "Libros favoritos") {
        this.favouriteBooks.push(cardData);
        this.favouriteBooks.sort((a, b) => b - a);
      }
      if (cardData.category === "Lo mejor de lo mejor") {
        this.loMejorDeLosMejores.push(cardData);
        this.bestOfTheBest.sort((a, b) => b - a);
      }
    });
  },
  métodos: {
    eliminar(categoría, índice) {
      if (category === "Libros leídos recientemente") {
        this.recentBooks.splice(index, 1);
      }
      if (category === "Libros favoritos") {
        this.librosfavoritos.splice(index, 1);
      }
      if (category === "Lo mejor de lo mejor") {
        this.loMejorDeLosMejores.splice(index, 1);
      }
    },
    edit(item, index) {
      if (item.category === "Libros leídos recientemente") {
        eventBus.$emit("abrir-añadir-libro-modal", item);
        this.recentBooks.splice(index, 1);
      }
      if (item.category === "Libros favoritos") {
        eventBus.$emit("abrir-añadir-libro-modal", item);
        this.librosfavoritos.splice(index, 1);
      }
      if (item.category === "Lo mejor de lo mejor") {
        eventBus.$emit("abrir-añadir-libro-modal", item);
        this.loMejorDeLosMejores.splice(index, 1);
      }
    }
  }
};
</script>

Si has llegado hasta aquí, ¡¡¡Gran trabajo!!! ¡Eres Impresionante!

Como se mencionó anteriormente, cada archivo .vue creado en la carpeta pages se aprovisiona automáticamente como una ruta, del mismo modo, para cada carpeta creada dentro de la carpeta pages. Esto no sólo es válido para páginas estáticas, ¡también se pueden crear páginas dinámicas de esta forma!

Veamos cómo.

Utilizando nuestro proyecto actual, digamos que queremos añadir una página dinámica para todas las fichas de libros con un botón de visualización para ver más detalles sobre un libro.

Añadamos rápidamente un botón de vista y utilicemos un para visitar la página. Sí, sustituye a y funciona.


                Ver
              

A continuación, creamos una carpeta dinámica anteponiendo al nombre un guión bajo. es decir, _title y dentro de esa carpeta, tendremos un archivo index.vue que se renderiza cuando visitamos esa ruta.

Sólo para demostración, sólo estaremos accediendo a la propiedad params dentro del archivo.

// _title/index.vue 

{{$route.params.title}}


Ahora, cuando hacemos clic en ver, se abre otra página donde podemos ver el título que hemos pasado por la ruta. Esto puede desarrollarse para hacer lo que queramos en lo que a páginas dinámicas se refiere.

¡Eso es todo por esta lección!

El código completo para esto se puede encontrar en este repositorio. Le invitamos a contribuir al código. Si usted está interesado en dominar el marco, entonces yo sugeriría este curso Udemy.