JavaScript: crear una aplicación MEVN simple

¿De qué trata el artículo?


El propósito de este artículo es mostrar cómo puede crear una aplicación MEVN básica. Acrónimo MEVN
significa - MongoDB + Express.js + Vue.js + Node.js. Como ejemplo, se escribirá
aplicación de una sola página que contiene un formulario que consta de varios textos
campos. Al completar el formulario y enviar datos, el servidor los escribirá en la base de datos y
redirija al cliente a la página de "Gracias".

Ubuntu 18.10 se utiliza como sistema operativo, la instalación de todos los componentes será
indicado en relación con ella.

Requerimientos Requeridos


  • Conocimiento de HTML, CSS;
  • Conocimientos básicos de JavaScript.

Lo que tenemos a la salida


  • Aplicación Fullstack completa;
  • Operaciones CRUD y API REST utilizando Express.js;
  • Conéctese a MongoDB.

Preparación del espacio de trabajo


Para comenzar a desarrollar la aplicación, debe instalar algunas herramientas.
La base de todo el proyecto es Node.js y su administrador de paquetes NPM. Node.js es un tiempo de ejecución
JavaScript, cuyo entorno incluye todo lo que necesita para ejecutar un programa,
escrito en javascript.

Puedes instalarlo aquí . La versión "Estable" debe seleccionarse como se indica en
captura de pantalla:

imagen

También puede usar NVM (Node Version Manager): esta es una herramienta conveniente para el control de versiones Node.js. Puede instalarlo desde la terminal con el comando:

env VERSION=`python tools/getnodeversion.py` make install DESTDIR=`nvm_version_path v$VERSION` PREFIX="" 

Entonces nvm use * version *, por ejemplo:

 nvm use 10 

Ahora Node.js está instalado, puede verificar esto con el comando node -v:

 node -v > 10.14.2 

Luego viene MongoDB. Este DBMS, clasificado como NoSQL, utiliza documentos similares a JSON y un esquema de base de datos.

imagen

Para instalar, debe ejecutar una secuencia de comandos:

 sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 9DA31620334BD75D9DCB49F368818C72E52529D4 echo "deb [ arch=amd64 ] https://repo.mongodb.org/apt/ubuntu bionic/mongodb-org/4.0 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-4.0.list sudo apt-get update sudo apt-get install -y mongodb-org 

Cuando MongoDB está instalado, puede ejecutarlo en segundo plano de esta manera:

 sudo systemctl start mongod 

Vue.js es un marco front-end para crear interfaces de usuario. Vue es completamente adecuado para crear aplicaciones de una sola página (SPA).

Para trabajar con Vue.js, hay una CLI (interfaz de línea de comandos) oficial: un sistema completo para un desarrollo rápido en Vue.js. Brindará la oportunidad de crear un proyecto de forma interactiva, así como la capacidad de actualizar y configuraciones óptimas para trabajar con el marco. Puede instalarlo usando NPM especificando el indicador -g (global) para que la dependencia se instale globalmente y pueda usarse fuera de un proyecto específico, es decir. globalmente:

 npm install -g @vue/cli 

Ahora que tiene el DBMS MongoDB y Node.js + NPM instalados, queda por decidir un editor de texto. Usaré VS Code como editor de texto. Puede elegir cualquier editor a su gusto: ya sea Sublime, Atom o incluso Notepad ++.

Inicializacion del proyecto


Para crear una nueva aplicación Vue.js, utilizaremos la CLI de Vue instalada previamente. El comando create se ve como vue create * app_name *:

 vue create mevn-app 

Aparece una interfaz en el terminal que le permite configurar los ajustes para la nueva aplicación. Seleccione "Seleccionar funciones manualmente" para configuraciones detalladas, haga la siguiente lista:

imagen

Al final de la generación de la aplicación, debería aparecer un mensaje similar:

imagen

Puede iniciar la aplicación con el comando npm run serve anterior y ver qué generó la CLI de Vue:

imagen

Esta página de inicio tiene la funcionalidad Vue Router (dos enlaces en la parte superior), complementos CLI instalados, así como enlaces a documentación, proyectos de ecosistemas Vue y redes sociales.

Así que ahora la jerarquía del proyecto creado se ve así:

imagen

  • node_modules: un directorio de dependencias instaladas necesarias para que el proyecto funcione. Por lo general, no está indexado en git, ya que su volumen a veces alcanza tamaños muy grandes.
  • package.json es un archivo de inicialización de proyecto que está estrechamente vinculado al directorio node_modules. Contiene información sobre el proyecto (nombre, autor, versión), se ejecutan scripts que ejecutan NPM, así como todas las dependencias instaladas que solo están contenidas en node_modules. Las dependencias se indican mediante los valores clave "dependencias" (dependencias utilizadas en la producción) y "devDependencies" (dependencias utilizadas en el desarrollo). Es decir este archivo es necesario principalmente para que el proyecto pueda implementarse en cualquier máquina, con solo el comando npm i. Puede intentar eliminar el directorio node_modules y luego ejecutar el comando npm i en la raíz del proyecto: volverá a extraer todas las dependencias necesarias que se especifican en package.json.
  • package-lock.json es una instantánea de todo el árbol de dependencias. El hecho es que los paquetes tienen dependencias de nivel superior. Al instalar, esto no se nota, pero siempre se puede ver en package-lock.json. Entonces, por ejemplo, el paquete bootstrap durante la instalación extraerá el paquete jquery junto con él. Jquery no se especificará en package.json, pero aún se instalará como una dependencia de arranque, es decir, no tiene que especificar adicionalmente jquery en "dependencias" para que bootstrap funcione correctamente.
  • babel.config.js es un archivo que contiene las reglas (preajustes) a través de las cuales Babel aprende a traducir el código. Babel es un transportista de código. El lenguaje JavaScript tiene especificaciones que debe seguir para que el código funcione correctamente en la producción. Pero a menudo no todos los navegadores logran implementar una nueva especificación en sus intérpretes, y algunas especificaciones nunca se implementan en absoluto. Para esto, Babel existe: traduce el código de una especificación a una especificación que la mayoría de los navegadores entienden. Es decir durante el desarrollo, escribes un código y, gracias a Babel, otro va a producción. En nuestro caso, solo hay un preajuste: '@ vue / app'.
  • postcss.config.js: archivo de configuración PostCSS. Esta es una herramienta de procesamiento posterior de CSS que puede transformar su CSS de muchas maneras geniales, por ejemplo, agregando prefijos automáticamente, verificando el cumplimiento del estándar de diseño de código y muchos otros. Vue CLI lo instala automáticamente y hasta ahora solo contiene reglas para agregar prefijos, lo que garantizará la aplicación entre navegadores.
  • browserslist.rc: un archivo que determina qué navegadores están diseñados para el desarrollo de aplicaciones. En nuestro caso, estas son las últimas 2 versiones de navegadores que tienen más del 5% de usuarios en todo el mundo, excluyendo Internet Explorer por debajo de la versión 8 inclusive.
  • README.md - un archivo con información del proyecto escrita en Markdown - un lenguaje de marcado liviano diseñado para escribir el texto más legible y fácil de editar. Por lo general, este archivo contiene una descripción del proyecto, información sobre las versiones de los paquetes principales, instrucciones de instalación, etc.
  • src (fuente): el directorio dentro del cual se lleva a cabo el desarrollo directamente. Contiene todo el código escrito, así como el directorio assets /, donde se ubican scss / css, js, fuentes, imágenes, etc. Vue.js utiliza Webpack para compilar: todo el código necesario para que la aplicación funcione correctamente se empaquetará en un único archivo vendor.js dentro del directorio dist /. Vale la pena agregar este directorio a .gitignor, como la aplicación ensamblada ocupa espacio adicional en el repositorio. Al igual que node_modules, dist / se puede compilar con un solo comando NPM.
  • public: el directorio que contiene la plantilla html básica para generar la aplicación finalizada y, por lo general, su ícono (favicon.ico).

Inicio del desarrollo (frontend)


Como usamos la CLI de Vue, en lugar de dividir el código en html, css y js, se crean archivos vue. No hay nada sobrenatural en esto: los archivos vue implican la siguiente estructura:

 <template> * HTML * </template> <script> * JavaScript * </script> <style> * Stylesheet * </style> 

Esto se hace para diseñar más convenientemente los componentes Vue y es solo azúcar sintáctico. Babel procesa los archivos con este formato para su posterior lanzamiento a producción.

En el directorio src /, además de los componentes Vue, también hay archivos main.js y router.js.
En main.js, Vue importa todos los paquetes necesarios, y luego crea una nueva instancia de Vue y la monta en el elemento especificado, en el nivel de DOM virtual, utilizando el método de clase Vue -. $ Mount ("# app"). Dentro del método, debe especificar una línea con la identificación del elemento html especificado en la plantilla html base.

En router.js, Vue importa el paquete vue-router que instaló la CLI de Vue al crear el proyecto y todos los componentes que intervienen en el enrutamiento. El enrutamiento ocurre al pasar, como argumento, una matriz de objetos a la clase Router, al crear su instancia:

 new Router({ routes: [ { path: '/', name: 'home', component: Home }, ... ] ) 

Primero, eliminemos los estilos Vue predeterminados de App.vue. Luego, debe eliminar los componentes / directorio junto con HelloWorld.vue, ya no serán necesarios. Además del directorio y el componente en sí, debe eliminar su importación dentro de views / Home.vue, donde se usa:

vistas / Home.vue:

 <template> <div class="home"> <img alt="Vue logo" src="../assets/logo.png"> - <HelloWorld msg="Welcome to Your Vue.js App"/> </div> </template> <script> - import HelloWorld from '@/components/HelloWorld.vue' export default { name: 'home', components: { - HelloWorld } } </script> 

Ahora la aplicación solo tiene un par de enlaces y sus representaciones. El contenido de estas páginas tampoco es necesario, pero no es necesario eliminarlas, simplemente puede cambiarlo, pero primero debe editar el archivo de enrutamiento:

router.js:

 import Vue from 'vue' import Router from 'vue-router' import Home from './views/Home.vue' + import Thanks from './views/Thanks.vue' Vue.use(Router) export default new Router({ routes: [ { path: '/', name: 'home', component: Home }, - { - path: '/about', - name: 'about', - component: () => import(/* webpackChunkName: "about" */ './views/About.vue') - } + { + path: '/thanks', + name: 'thanks', + component: Thanks + } ] }) 

Ahora pasamos a los componentes, confiando en un sistema de enrutamiento. Necesita un nuevo componente de agradecimiento. En lugar de crear uno nuevo, edite About.vue y cámbiele el nombre Thanks.vue:

views / About.vue> views / Thanks.vue:

 <template> - <div class="about"> + <div class="thanks"> <h1>Thank you for your record!</h1> </div> </template> 

Y cambie Home.vue: agregue un formulario que enviará datos como Nombre, Correo electrónico, Dirección y Género:

vistas / Home.vue:

 <template> <div class="home"> - <img alt="Vue logo" src="../assets/logo.png"> + <form @submit.prevent="sendData"> + <div class="form-control"> + <label for="name">Name</label> + <input v-model="name" id="name" type="text"> + </div> + <div class="form-control"> + <label for="email">Email</label> + <input v-model="email" id="email" type="email"> + </div> + <div class="form-control"> + <label for="address">Address</label> + <input v-model="address" id="address" type="text"> + </div> + <div class="form-control"> + <label for="gender">Gender</label> + <span>Male <input v-model="gender" id="gender" type="radio" value="male"></span> + <span>Female <input v-model="gender" id="gender" type="radio" value="female"></span> + </div> + <input type="submit" class="send" value="Send"> + </form> </div> </template> <script> export default { name: 'home', - components: {} + data: function () { + return { + name: '', + email: '', + address: '', + gender: '', + + }, + methods: { + sendData() { + console.log(this.name, this.email, this.address, this.gender); + + } </script> + <style> + .form-control { + padding: 5px; + } + .form-control label { + display: block; + + .send { + margin: 5px + + </style> 

Lo primero que puede ser engañoso es @ submit.prevent = "sendData". En Vue, los eventos se escuchan usando el atributo v-on: pero como este atributo se usa con bastante frecuencia durante el desarrollo, se inventó su abreviatura @. Es decir esta línea se puede representar como v-on: submit.prevent = "sendData".

Veamos qué significa esto generalmente:

  • v-on o @ le dice a Vue que escuche un evento;
  • enviar: este es el evento dado (enviar solo se aplica a los formularios. Para un botón, por ejemplo, puede aplicar el evento de clic y para ingresar, ingresar o cambiar);
  • .prevent es un modificador de eventos que llama al controlador preventDefault () js, que detiene el evento del navegador para un elemento, en nuestro caso, un formulario. El evento del navegador para el formulario es enviar datos y volver a cargar la página, lo que debe evitarse. Además, existen modificadores como .stop (eliminación completa del evento del navegador), .once (ejecución del método solo una vez) y otros.
  • sendData es el método (función dentro del objeto) que se llamará cuando se procese el evento. Tenga en cuenta que los corchetes () del método deben colocarse solo si acepta parámetros.

Además, en cada entrada hay un atributo v-model. Vincula bidireccionalmente elementos de formulario (input, select, textarea) con datos. Es decir, el valor escrito en la entrada, donde v-model = "someText", se escribirá inmediatamente en la propiedad de datos someText, si existe.

En el objeto exportado, eliminamos la propiedad componentes, porque Home.vue no tendrá componentes secundarios, pero agregamos el método de datos. Los datos contienen el objeto de datos Vue. Vale la pena señalar que no puede simplemente escribir el valor de los datos como un objeto con datos, definitivamente debe escribir el valor como una función que lo devuelve. Esta es una característica de los componentes Vue.
En nuestro caso, los datos son los valores de entrada nombre, correo electrónico, dirección y género.

Además de los datos, ha aparecido una propiedad de métodos que contiene todos los métodos para trabajar con datos. Solo se escribe un método: sendData, que se mencionó anteriormente. Está vinculado a enviar el formulario y por ahora solo muestra los valores de entrada en la consola.

Y la última parte del componente es el estilo. Los estilos se escriben aquí para que el formulario se muestre correctamente.

Abramos nuestra aplicación ahora. Ante nosotros hay un formulario que debe completarse y enviar datos utilizando el botón Enviar.

imagen

imagen

Al enviar, la página no se vuelve a cargar y los valores del formulario no se restablecen. Es hora de mirar en la consola del navegador (Ctrl + Shift + I):

imagen

Si ve lo mismo en la consola, solo con los valores que especificó: felicitaciones, escribió su primera aplicación Vue completa. De lo contrario, debe verificar la corrección de cada paso y llegar a un resultado positivo.

Por ahora, dejemos la aplicación Vue como está y avancemos al desarrollo del servidor en Node.js para que la aplicación tenga algo con lo que intercambiar datos.

Desarrollo continuo (backend)


Primero necesita instalar los paquetes npm necesarios para la operación del servidor:

 npm install -S express morgan mongoose 

El modificador -S le dice a npm que agregue estos paquetes a package.json como un elemento de la matriz de dependencias. El resultado será un mensaje similar:

imagen

  • Express.js es un marco de aplicación web para Node.js diseñado para crear aplicaciones web y API. Es minimalista e incluye una gran cantidad de complementos.
  • Morgan: un paquete para registrar solicitudes HTTP en el servidor.
  • Mongoose es un ORM (mapeo relacional de objetos) para MongoDB hecho bajo Node.js.

Luego agregue otro directorio al servidor raíz del proyecto, con la siguiente jerarquía:

imagen

server.js: este será el servidor Node.js, que se inicia utilizando el entorno Node. Puede probar Node escribiendo un código simple aquí, por ejemplo:

server / server.js
 console.log('Hello, world!'); 

Luego, inicie server.js utilizando el comando de nodo desde la raíz del proyecto, especificando la ruta al archivo y su nombre:

 node server/server.js > Hello, world! 

Borraremos el archivo server.js y comenzaremos el desarrollo. Primero, importe todos los paquetes instalados previamente (express, morgan y mongoose), y también inicialice la aplicación Express:

server / server.js

 + const express = require('express'); + const mongoose = require('mongoose'); + const morgan = require('morgan'); + const path = require('path'); + + const app = express(); 

Si nunca antes ha encontrado const: const, una de las dos declaraciones de declaración de variables (el segundo let) vino a reemplazar a var, el estándar ES6. Su peculiaridad es que el valor asignado a una variable no se puede cambiar. Para variables con valores variables adicionales, se recomienda usar let.

require () es una función del entorno Node.js que implementa la capacidad de conectar varios módulos, tanto nativos como npm. Tenga en cuenta que no instalamos el paquete de ruta, pero lo importamos, ya está incluido en las dependencias del entorno.

const app = express () - inicialización de la aplicación Express. A continuación, trabajaremos con la variable de la aplicación, este será nuestro servidor.

A continuación, debe establecer la configuración de nuestra aplicación Express, pero como es pequeña, debe establecer solo un parámetro: puerto. Tome, por ejemplo, el valor 3000 (o cualquier puerto disponible). Después de comenzar a escuchar el puerto, es decir iniciar el servidor:

server / server.js

 ... + app.set('port', 3000); + + app.listen(app.get('port'), () => { + console.log(`[OK] Server is running on localhost:${app.get('port')}`); + }); 

El método set simplemente agrega la propiedad especificada al objeto especificado con el valor especificado, que luego se puede obtener accediendo al nombre de la propiedad con el método get. Esto es exactamente lo que hacemos cuando configuramos la aplicación para que escuche: app.get ('puerto') devolverá el valor previamente establecido de 3000. Después de recibir el puerto, se activa una función de devolución de llamada de flecha. Si nunca antes ha encontrado funciones de flecha: la función de flecha se denota como () => {} y es casi una analogía completa de la función () {}, excepto por una: la función de flecha tiene un objeto global como contexto para llamar a la función (esto) (Global en el entorno Node.js y Window en el entorno del navegador), y la función habitual en sí misma, es decir Función En esta situación, la función de flecha simplemente simplifica la grabación, ya que No usamos esto de ninguna manera. Entonces, como una función de devolución de llamada, simplemente se ejecuta un mensaje en la consola que indica que el servidor se ejecuta en localhost: 3000. Escribir $ {...} dentro de la cadena le permite insertar un valor calculado en ella, en nuestro caso, el valor de retorno de la función app.get ().

Ahora, abriendo la dirección localhost: 3000 en su navegador, verá el mensaje "No se puede OBTENER /". Esto significa que nuestro servidor se ha iniciado y funciona correctamente. Más tarde haremos que nuestra aplicación Vue.js aparezca en lugar de este mensaje, pero por ahora estableceremos una conexión con la base de datos MongoDB y el middleware:

server / server.js

 ... app.set('port', 3000); + + mongoose.connect('mongodb://localhost:27017/mevn-course', { useNewUrlParser: true }) + then(db => console.log('[OK] DB is connected')) + catch(err => console.error(err)); + + app.use(express.json()); + app.use(express.urlencoded({extended: false})); + app.use(morgan('dev')); ... 

Mongoose.connect () se conecta a la base de datos. Tenga en cuenta que MongoDB debe estar activo antes de conectarse nuevamente. Se pasan dos parámetros a este método: la dirección base y un conjunto de configuraciones en forma de objeto. En nuestro caso, esta es la cadena "mongodb: // localhost: 27017 / mevn-course" y el objeto {useNewUrlParser: true}.

useNewUrlParser se usa para trabajar con MongoDB versión 3.1.0+. Si por alguna razón está utilizando una versión inferior a 3.1.0, no debe especificar este parámetro.

.then y .catch son métodos que devuelven una Promesa al cumplirse y fallar, respectivamente. Dentro de estos métodos, se llama a una función de devolución de llamada, que devuelve el objeto de base de datos db como resultado de la Promesa para .then, y un error para .catch. Ambos métodos imprimen información en la consola: ya sea sobre una conexión exitosa o sobre un error.

Usando app.use (), se instala middleware para nuestra aplicación. Estas son funciones que tienen acceso al objeto de solicitud (req), el objeto de respuesta (res) y la siguiente función de procesamiento intermedio (siguiente) en el ciclo de "solicitud-respuesta" de la aplicación. Utilizaremos como middleware los analizadores integrados en Express que vienen con las solicitudes de datos (en nuestro caso, son json y urlencoded) y el paquete morgan instalado anteriormente con el parámetro 'dev', lo que significa iniciar sesión en el modo "desarrollo". Ahora el servidor puede recibir datos entrantes con solicitudes en formato json y urlencoded y registrar todas las solicitudes entrantes. Inicie la aplicación nuevamente:

nodo servidor / servidor.js

 > [OK] Server is running on localhost:3000 > [OK] DB is connected 

Ahora, si vamos a la dirección localhost: 3000 en el navegador, todas las solicitudes se registrarán en la consola, en este caso la solicitud GET:

imagen

Nos dedicaremos al desarrollo del modelo Record. Esto es necesario para que los datos se envíen a la base de datos en el formato deseado (este formato se llama esquema). Nuestro formulario de la aplicación Vue envía Nombre, Correo electrónico, Dirección y Género; todo esto se puede representar como una cadena. Por lo tanto, el registro en la base de datos debe contener 4 campos del tipo "fila". Crea un modelo:

servidor / modelos / Record.js

 + const mongoose = require('mongoose'); + const { Schema } = mongoose; + + const Record = new Schema({ + name: String, + email: String, + address: String, + gender: String, + }); + + module.exports = mongoose.model('Record', Record); 

Importamos el paquete de mangosta y establecemos la variable Schema en el valor de la clase Schema del paquete de mangosta. La notación "const {Schema} = mangosta" se llama desestructuración en ES6 y es equivalente a "const Schema = mongoose.Schema". A continuación, se crea una instancia de la clase Schema, cuyo parámetro es un objeto con los nombres de las propiedades de registro y sus tipos de datos.
"Module.exports = ..." es una entrada de exportación. Es decir cuando importamos este módulo, el resultado de la importación será mongoose.model ('Grabar', Grabar).

Cuando se crea el modelo, debe crear un archivo de enrutamiento API. Como estilo arquitectónico de interacción de componentes, se utilizará REST.La API REST define un conjunto de funciones a las que los desarrolladores pueden realizar solicitudes y recibir respuestas. La interacción tiene lugar a través del protocolo HTTP. Los métodos de llamada REST API son metodología CRUD (Crear, Leer, Actualizar, Eliminar), es decir OBTENER, PUBLICAR, PONER, BORRAR. Agregue el código al archivo de enrutamiento:

server / models / Record.js

 + const express = require('express'); + const router = express.Router(); + + const Record = require('../models/Record'); + + router.get('/', async (req, res) => { + res.json(await Record.find()); + }); + + router.post('/', async (req, res) => { + const record = new Record(req.body); + await record.save(); + res.json({state: 'success'}); + }); + + router.get('/:id', async (req, res) => { + res.json(await Record.findById(req.params.id)); + }); + + router.put('/:id', async (req, res) => { + await Record.findByIdAndUpdate(req.params.id, req.body); + res.json({state: 'updated'}); + }); + + router.delete('/:id', async (req, res) => { + await Record.findByIdAndRemove(req.params.id); + res.json({state: 'deleted'}); + }); + + module.exports = router; 

Importamos el paquete Express y creamos el objeto enrutador. También importamos el módulo Modelo de registro para interactuar con la base de datos. Lo siguiente simplemente describe el enrutamiento. La construcción async / await es una forma relativamente nueva de escribir código asincrónico. Anteriormente, se escribía un código similar utilizando funciones y promesas de devolución de llamada. Gracias a async / await, el código asincrónico se vuelve similar al síncrono, y en su comportamiento aparecen características de dicho código, que son muy útiles en algunas situaciones en las que las promesas de uso fueron, por diversas razones, inconvenientes.

En cambio:

 router.get('/', req, res) => { res.json(Record.find() .then((data) => { return data; })); }); 

Tenemos:

 router.get('/', async (req, res) => { res.json(await Record.find()); }); 

Los métodos de enrutador como .get (), .post (), .put () y .delete () le dan al servidor una comprensión de cómo se deben manejar ciertas solicitudes. Dentro de los métodos hay una función de devolución de llamada ejecutada asincrónicamente con dos parámetros req: el objeto de solicitud y res: el objeto de respuesta. En todos los métodos, excepto el método POST, se accede a la base de datos de forma asincrónica utilizando los métodos del modelo Record, como find (), findById (), findByIdAndUpdate (), findByIdAndRemove (). Luego viene la respuesta del servidor en formato JSON, por ejemplo, res.json ({state: 'success'}). El procesamiento del método POST es diferente: primero se crea una instancia de la clase Record, cuyo parámetro es el cuerpo de solicitud que proviene de la aplicación Vue, luego la instancia se guarda de forma asíncrona en la base de datos utilizando el método save (), y solo luego la respuesta se envía en el formato JSON Tambiénpreste atención a las últimas tres consultas: obtener, poner y eliminar, en la dirección que tienen: id. Esto significa que todo lo que se escribirá en la dirección después de "/" estará disponible como el valor de req.params.id y se presentará como una cadena. para que podamos acceder por id.
Quizás surja la pregunta, ¿por qué identificación tendremos acceso a los registros en la base de datos si Schema contiene solo los campos nombre, correo electrónico, dirección y género? Respuesta: MongoDB crea un identificador para cada registro, que se llamará _id.

El modelo y el enrutamiento están escritos, solo queda importar el módulo deseado en server.js:

server / server.js

 ... app.use(morgan('dev')); + + app.use('/api/records', require('./routes/records')); 

Esta entrada significa que la ruta que escribimos comenzará con / api / records. Es decir, para agregar un nuevo registro, debe enviar una solicitud POST con un cuerpo que contenga datos válidos (nombre, correo electrónico, dirección y género) a localhost : 3000 / api / records.

Asegúrese de que el servidor funciona: ejecútelo y pruebe la API. Yo uso Postman para esto. Esta es una herramienta de prueba API completa.

Una solicitud GET en localhost : 3000 / api / records ahora devuelve una matriz vacía:

imagen

en este caso, ejecutaremos una solicitud POST en la misma dirección, en cuyo cuerpo indicaremos datos válidos para escribir en la base de datos:

imagen

vemos que la respuesta del servidor vino en formato JSON como señalamos, este mensaje
{"Estado": "éxito"}. Ejecutamos la solicitud GET anterior nuevamente:

imagen

todo resultó , puede probar independientemente las operaciones restantes en los datos (ACTUALIZAR, ELIMINAR o OBTENER uno).

El desarrollo de la parte de back-end ha llegado a su fin, queda por hacer el toque final: designe los archivos estáticos para mostrar en localhost : 3000 /. Agregue el código:

server / server.js

 ... app.use('/api/records', require('./routes/records')); + app.use('/', express.static(path.join(__dirname, '../dist'))); 

Desarrollo continuo (frontend)


Volviendo a la aplicación Vue, ahora hay una API con la que puede interactuar. Por lo tanto, sin perder tiempo, cambiaremos el método sendData escrito anteriormente, pero primero, usando npm, instalaremos el paquete axios - npm i -S axios.

vistas / Home.vue

 ... <script> + import axios from 'axios'; ... methods: { + async sendData() { - console.log(this.name, this.email, this.address, this.gender); + console.log(await axios({ + url: 'http://localhost:3000/api/records', + method: 'post', + data: { + name: this.name, + email: this.email, + address: this.address, + gender: this.gender + + })); } } 

Axios es una biblioteca cliente para enviar solicitudes a un servidor que utiliza promesas predeterminadas. Aquí usamos la construcción asíncrona / espera familiar. Se pasa un objeto a la función axios: un conjunto de opciones (url, método, datos). Cuando se ejecuta el método, se envía la solicitud.

Ahora ejecute el comando npm run build. Al usarlo, Vue ensamblará la aplicación terminada en el directorio dist, que especificamos como archivos estáticos para el servidor:

 npm run build 

imagen

Luego reiniciamos el servidor y en el navegador vamos a localhost : 3000 /. Exactamente, ahora nuestra aplicación Vue se muestra aquí. Complete el formulario y envíe los datos haciendo clic en Enviar. Observamos la consola:

imagen

la respuesta del servidor se devuelve como datos. Esto significa que se ha agregado el registro y nuestra aplicación funciona como debería.

Ahora haremos los toques finales en la aplicación: redirigir al enviar el formulario a la página de agradecimiento; la posibilidad de ir de la página de agradecimiento a la página principal, eliminar enlaces de la barra de navegación, eliminar console.log ():

views / Thanks.vue

 <template> <div class="thanks"> <h1>Thank you for your record!</h1> + router-link to="/">Home</router-link> </div> </template> 

vistas / Home.vue

 ... async sendData() { - console.log(await axios({ + await axios({ url: 'http://localhost:3000/api/records', method: 'post', data: { name: this.name, email: this.email, address: this.address, gender: this.gender } - })); + }); + this.$router.push('thanks'); } ... 

App.vue

 ... <div id="app"> - <div id="nav"> - <router-link to="/">Home</router-link> | - <router-link to="/thanks">About</router-link> - </div> <router-view/> </div> ... 

Nuestra aplicación Vue está completamente lista, la recopilamos usando npm run build, reiniciamos el servidor, verificamos la operatividad.

Desarrollo completado (backend)


Sería bueno que el servidor envíe una notificación por correo electrónico cuando un cliente agrega cada nuevo registro a la base de datos. Para hacer esto, utilizaremos el servicio para enviar cartas a Node.js - Nodemailer. Instalarlo: npm install -S nodemailer. Ahora que Nodemailer está instalado, agregue funcionalidad a server.js:

server / routes / records.js

 ... const router = express.Router(); + const nodemailer = require('nodemailer'); ... router.post('/', async (req, res) => { const record = new Record(req.body); await record.save(); + const output = ` + <p>You have a new message from MEVN-course:</p> + <ul> + <li>name: ${req.body.name}</li> + <li>email: ${req.body.email}</li> + <li>address: ${req.body.address}</li> + <li>gender: ${req.body.gender}</li> + </ul> + `; + let transporter = nodemailer.createTransport({ + host: 'smtp.gmail.com', + port: 587, + secure: false, + auth: { + user: 'your_email@gmail.com', + pass: 'your_password' + + }); + let mailOptions = { + from: '"MEVN-course " <your_email@gmail.com>', + to: 'some_email@gmail.com', + subject: `MEVN-course | New message`, + text: req.body.name, + html: output + }; + transporter.sendMail(mailOptions, (error, info) => { + if (error) { + return console.log(error); + + console.log('Message sent: %s', info.messageId); + console.log('Preview URL: %s', nodemailer.getTestMessageUrl(info)); + }); res.json({state: 'success'}); }); 

Veamos qué pasa aquí. Primero, se importa el paquete nodemailer instalado previamente. En segundo lugar, se cambia el método de publicación para que, además de guardar el registro en la base de datos, el servidor también envíe una notificación al correo. Primero, se crea la variable de salida, en la que se escribe el marcado html. Luego, la variable transportadora se crea utilizando el método createTransport del objeto de nodo de correo al que se transfiere el objeto, un conjunto de opciones para autenticar la cuenta de correo: nombre de host, puerto, así como inicio de sesión y contraseña. Tenga en cuenta que si usa Gmail, además de la autenticación, deberá permitir que aplicaciones de terceros usen el buzón en la configuración de su cuenta de Gmail. A continuación, se crea la variable mailOptions, en la que se escribe el objeto: las opciones de letra: desde quién se envió el mensaje, a quién se envió, el asunto de la carta y su cuerpo. Y finalmenteutilizando el método sendMail del objeto transportador, se envía la carta.

Reiniciamos el servidor y probamos. Si la información de autenticación es correcta y la configuración de la cuenta permite el uso de un buzón por parte de aplicaciones de terceros, se enviará el mensaje y se enviará un mensaje a la consola sobre el envío exitoso; de lo contrario, el error también se indicará en la consola. Parece un envío exitoso:

imagen

por lo tanto, uno no exitoso:

imagen

Resumen


En este desarrollo de aplicaciones llegó a su fin. Que tenemos

  • experiencia en el desarrollo de aplicaciones Vue;
  • experiencia en el desarrollo del servidor Node + Express;
  • experiencia con MongoDB;
  • experiencia con npm;
  • capacidad de organizar páginas de redireccionamiento;
  • la capacidad de organizar boletines de correo electrónico desde el servidor;
  • la capacidad de enviar desde el cliente y recibir solicitudes http en el servidor;
  • comprensión de CRUD y REST API;

Source: https://habr.com/ru/post/457580/


All Articles