Worum geht es in dem Artikel?
In diesem Artikel wird gezeigt, wie Sie eine grundlegende MEVN-Anwendung erstellen können. Akronym MEVN
bedeutet - MongoDB + Express.js + Vue.js + Node.js. Als Beispiel wird es geschrieben
Einzelseitenanwendung, die ein Formular enthält, das aus mehreren Texten besteht
Felder. Wenn Sie das Formular ausfüllen und Daten senden, schreibt der Server diese in die Datenbank
Leiten Sie den Client auf die Seite "Danke" weiter.
Ubuntu 18.10 wird als Betriebssystem verwendet, die Installation aller Komponenten erfolgt
relativ zu ihr angegeben.
Erforderliche Anforderungen
- Kenntnisse in HTML, CSS;
- Grundkenntnisse in JavaScript.
Was wir am Ausgang haben
- Vollwertige Fullstack-Anwendung;
- CRUD-Operationen und REST-APIs mit Express.js;
- Stellen Sie eine Verbindung zu MongoDB her.
Vorbereitung des Arbeitsbereichs
Um mit der Entwicklung der Anwendung zu beginnen, müssen Sie einige Tools installieren.
Die Basis des gesamten Projekts ist Node.js und sein NPM-Paketmanager. Node.js ist eine Laufzeit
JavaScript, dessen Umgebung alles enthält, was Sie zum Ausführen eines Programms benötigen,
geschrieben in Javascript.
Sie können es hier installieren . Die Version „Stabil“ sollte wie unter ausgewählt ausgewählt werden
Screenshot:

Sie können auch NVM (Node Version Manager) verwenden - dies ist ein praktisches Tool zur Versionskontrolle von Node.js. Sie können es vom Terminal mit dem folgenden Befehl installieren:
env VERSION=`python tools/getnodeversion.py` make install DESTDIR=`nvm_version_path v$VERSION` PREFIX=""
Verwenden Sie dann nvm * version *, zum Beispiel:
nvm use 10
Nachdem Node.js installiert ist, können Sie dies mit dem Befehl node -v überprüfen:
node -v > 10.14.2
Als nächstes kommt MongoDB. Dieses als NoSQL klassifizierte DBMS verwendet JSON-ähnliche Dokumente und ein Datenbankschema.

Zur Installation müssen Sie eine Folge von Befehlen ausführen:
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
Wenn MongoDB installiert ist, können Sie es wie folgt im Hintergrund ausführen:
sudo systemctl start mongod
Vue.js ist ein Front-End-Framework zum Erstellen von Benutzeroberflächen. Vue eignet sich vollständig zum Erstellen von Single-Page-Anwendungen (SPA).
Für die Arbeit mit Vue.js gibt es eine offizielle CLI (Command Line Interface) - ein komplettes System für die schnelle Entwicklung auf Vue.js. Es bietet die Möglichkeit, interaktiv ein Projekt zu erstellen und die Einstellungen für die Arbeit mit dem Framework zu aktualisieren und zu optimieren. Sie können es mit NPM installieren, indem Sie das Flag -g (global) angeben, sodass die Abhängigkeit global installiert wird und außerhalb eines bestimmten Projekts verwendet werden kann, d. H. global:
npm install -g @vue/cli
Nachdem Sie DBMS MongoDB und Node.js + NPM installiert haben, müssen Sie sich noch für einen Texteditor entscheiden. Ich werde VS Code als Texteditor verwenden. Sie können jeden Editor nach Ihrem Geschmack auswählen: ob Sublime, Atom oder sogar Notepad ++.
Projektinitialisierung
Um eine neue Vue.js-Anwendung zu erstellen, verwenden wir die zuvor installierte Vue-CLI. Der Befehl create sieht wie folgt aus: vue create * app_name *:
vue create mevn-app
Im Terminal wird eine Schnittstelle angezeigt, über die Sie Einstellungen für die neue Anwendung konfigurieren können. Wählen Sie "Manuelle Auswahl von Funktionen" für detaillierte Einstellungen und erstellen Sie die folgende Liste:

Am Ende der Anwendungsgenerierung sollte eine ähnliche Meldung angezeigt werden:

Sie können die Anwendung mit dem obigen Befehl npm run serve starten und sehen, was die Vue-CLI generiert hat:

Diese Startseite enthält Vue Router-Funktionen (zwei Links oben), installierte CLI-Plugins sowie Links zu Dokumentation, Vue-Ökosystemprojekten und sozialen Netzwerken.
Die Hierarchie des erstellten Projekts sieht nun folgendermaßen aus:

- node_modules - Ein Verzeichnis der installierten Abhängigkeiten, die für das Funktionieren des Projekts erforderlich sind. Normalerweise wird es nicht in git indiziert, da sein Volumen erreicht manchmal sehr große Größen.
- package.json ist eine Projektinitialisierungsdatei, die sehr eng mit dem Verzeichnis node_modules verknüpft ist. Es enthält Informationen zum Projekt (Name, Autor, Version), Skripte, die NPM ausführen, sowie alle installierten Abhängigkeiten, die nur in node_modules enthalten sind. Abhängigkeiten werden durch die Schlüsselwerte "Abhängigkeiten" (in der Produktion verwendete Abhängigkeiten) und "devDependencies" (in der Entwicklung verwendete Abhängigkeiten) angegeben. Das heißt, Diese Datei wird hauptsächlich benötigt, damit das Projekt mit nur dem Befehl npm i auf jedem Computer bereitgestellt werden kann. Sie können versuchen, das Verzeichnis node_modules zu entfernen, und dann den Befehl npm i im Stammverzeichnis des Projekts ausführen: Alle erforderlichen Abhängigkeiten, die in package.json angegeben sind, werden erneut abgerufen.
- package-lock.json ist eine Momentaufnahme des gesamten Abhängigkeitsbaums. Tatsache ist, dass Pakete Abhängigkeiten auf oberster Ebene aufweisen. Bei der Installation fällt dies nicht auf, aber Sie können es immer in package-lock.json sehen. So zieht beispielsweise das Bootstrap-Paket während der Installation das jquery-Paket mit. Jquery wird nicht in package.json angegeben, wird jedoch weiterhin als Bootstrap-Abhängigkeit installiert, d. H. Sie müssen jquery nicht zusätzlich in "Abhängigkeiten" angeben, damit Bootstrap ordnungsgemäß funktioniert.
- babel.config.js ist eine Datei mit den Regeln (Voreinstellungen), anhand derer Babel lernt, wie man den Code übersetzt. Babel ist ein Codetransporter. Die JavaScript-Sprache enthält Spezifikationen, die Sie befolgen müssen, damit der Code in der Produktion ordnungsgemäß funktioniert. Oft schaffen es jedoch nicht alle Browser, eine neue Spezifikation in ihren Interpreten zu implementieren, und einige Spezifikationen werden überhaupt nicht implementiert. Dafür gibt es Babel: Es übersetzt Code aus einer Spezifikation in eine Spezifikation, die die meisten Browser verstehen. Das heißt, Während der Entwicklung schreiben Sie einen Code und dank Babel geht ein anderer in die Produktion. In unserem Fall gibt es nur eine Voreinstellung - '@ vue / app'.
- postcss.config.js - PostCSS-Konfigurationsdatei. Dies ist ein CSS-Nachbearbeitungswerkzeug, mit dem Sie Ihr CSS auf viele coole Arten transformieren können, z. B. indem Sie automatisch Präfixe hinzufügen, die Einhaltung des Code-Design-Standards überprüfen und viele andere. Es wird automatisch von Vue CLI installiert und enthält bisher nur Regeln zum Hinzufügen von Präfixen, die eine browserübergreifende Anwendung gewährleisten.
- browsererslist.rc - Eine Datei, die bestimmt, welche Browser für die Anwendungsentwicklung ausgelegt sind. In unserem Fall sind dies die letzten beiden Versionen von Browsern mit mehr als 5% der Benutzer weltweit, ausgenommen Internet Explorer unter Version 8 einschließlich.
- README.md - eine Datei mit Projektinformationen, die in Markdown geschrieben wurden - einer einfachen Markup-Sprache, mit der der am besten lesbare und einfach zu bearbeitende Text geschrieben werden kann. Normalerweise enthält diese Datei eine Beschreibung des Projekts, Informationen zu den Versionen der Hauptpakete, Installationsanweisungen usw.
- src (Quelle) - das Verzeichnis, in dem die Entwicklung direkt stattfindet. Es enthält den gesamten geschriebenen Code sowie das Assets / Verzeichnis, in dem scss / css, js, Schriftarten, Bilder usw. abgelegt sind. Vue.js verwendet Webpack zum Erstellen: Der gesamte Code, der für die ordnungsgemäße Funktion der Anwendung erforderlich ist, wird in eine einzelne Datei vendor.js im Verzeichnis dist / gepackt. Es lohnt sich, dieses Verzeichnis zu .gitignor hinzuzufügen, as Die zusammengestellte Anwendung belegt zusätzlichen Speicherplatz im Repository. Wie node_modules kann dist / mit einem einzigen NPM-Befehl kompiliert werden.
- public - das Verzeichnis, das die grundlegende HTML-Vorlage zum Generieren der fertigen Anwendung und normalerweise das Symbol (favicon.ico) enthält.
Entwicklungsbeginn (Frontend)
Da wir die Vue-CLI verwenden, werden Vue-Dateien erstellt, anstatt den Code in separate HTML-, CSS- und JS-Dateien aufzuteilen. Daran ist nichts Übernatürliches: Vue-Dateien implizieren die folgende Struktur:
<template> * HTML * </template> <script> * JavaScript * </script> <style> * Stylesheet * </style>
Dies geschieht, um Vue-Komponenten bequemer zu gestalten, und ist nur syntaktischer Zucker. Es sind die Dateien mit diesem Format, die von Babel für die spätere Freigabe in die Produktion verarbeitet werden.
Im Verzeichnis src / befinden sich neben den Vue-Komponenten auch die Dateien main.js und router.js.
In main.js importiert Vue alle erforderlichen Pakete, erstellt dann eine neue Vue-Instanz und hängt sie auf der Ebene des virtuellen DOM mithilfe der Vue-Klassenmethode -. $ Mount (”# app”) in das angegebene Element ein. Innerhalb der Methode sollten Sie eine Zeile mit der ID des HTML-Elements angeben, das in der Basis-HTML-Vorlage angegeben ist.
In router.js importiert Vue das Vue-Router-Paket, das die Vue-CLI beim Erstellen des Projekts installiert hat, sowie alle Komponenten, die am Routing beteiligt sind. Das Routing erfolgt, indem beim Erstellen der Instanz ein Array von Objekten als Argument an die Router-Klasse übergeben wird:
new Router({ routes: [ { path: '/', name: 'home', component: Home }, ... ] )
Entfernen wir zunächst die Standard-Vue-Stile aus App.vue. Dann sollten Sie die Komponenten / das Verzeichnis zusammen mit HelloWorld.vue löschen, sie werden nicht mehr benötigt. Zusätzlich zum Verzeichnis und der Komponente selbst sollten Sie den Import in views / Home.vue entfernen, wo er verwendet wird:
Ansichten / 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>
Jetzt hat die Anwendung nur noch ein paar Links und deren Darstellungen. Der Inhalt dieser Seiten wird ebenfalls nicht benötigt, aber es ist nicht notwendig, sie zu löschen. Sie können ihn einfach ändern, aber zuerst müssen Sie die Routing-Datei bearbeiten:
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( './views/About.vue') - } + { + path: '/thanks', + name: 'thanks', + component: Thanks + } ] })
Jetzt gehen wir zu Komponenten über und verlassen uns auf ein Routing-System. Benötigen Sie eine neue Danke-Komponente. Anstatt ein neues zu erstellen, bearbeiten Sie About.vue und benennen Sie es in Thanks.vue um:
Ansichten / About.vue> Ansichten / Thanks.vue: <template> - <div class="about"> + <div class="thanks"> <h1>Thank you for your record!</h1> </div> </template>
Und ändern Sie Home.vue: Fügen Sie ein Formular hinzu, das Daten wie Name, E-Mail, Adresse und Geschlecht sendet:
Ansichten / 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>
Das erste, was irreführend sein kann, ist @ submit.prevent = "sendData". In Vue werden Ereignisse mit dem Attribut v-on: gehört. Da dieses Attribut jedoch während der Entwicklung häufig verwendet wird, wurde die Abkürzung @ erfunden. Das heißt, Diese Zeile kann als v-on dargestellt werden: submit.prevent = "sendData".
Mal sehen, was dies allgemein bedeutet:
- v-on oder @ weist Vue an, ein Ereignis anzuhören.
- Senden - Dies ist das angegebene Ereignis (Senden gilt nur für Formulare. Für eine Schaltfläche können Sie beispielsweise das Klickereignis anwenden und für Eingabe - Eingabe oder Änderung).
- .prevent ist ein Ereignismodifikator, der den jD-Handler präventDefault () aufruft, der das Browserereignis für ein Element - in unserem Fall ein Formular - anhält. Das Browserereignis für das Formular sendet Daten und lädt die Seite neu, was vermieden werden sollte. Es gibt auch Modifikatoren wie .stop (vollständiges Entfernen des Browserereignisses), .once (nur einmaliges Ausführen der Methode) und andere.
- sendData ist die Methode (Funktion innerhalb des Objekts), die aufgerufen wird, wenn das Ereignis verarbeitet wird. Bitte beachten Sie, dass Klammern () für die Methode nur gesetzt werden sollten, wenn sie Parameter akzeptiert.
Ferner gibt es an jeder Eingabe ein V-Modell-Attribut. Es bindet bidirektional Formelemente (Eingabe, Auswahl, Textbereich) mit Daten. Das heißt, der in die Eingabe geschriebene Wert, wobei v-model = "someText" ist, wird sofort in die Dateneigenschaft someText geschrieben, sofern vorhanden.
Im exportierten Objekt entfernen wir die Komponenteneigenschaft, weil Home.vue hat keine untergeordneten Komponenten, aber wir fügen die Datenmethode hinzu. Die Daten enthalten das Vue-Datenobjekt. Es ist erwähnenswert, dass Sie den Wert von Daten nicht nur als Objekt mit Daten schreiben können - Sie müssen den Wert definitiv als eine Funktion schreiben, die ihn zurückgibt. Dies ist eine Funktion von Vue-Komponenten.
In unserem Fall sind die Daten die Eingabewerte Name, E-Mail, Adresse und Geschlecht.
Zusätzlich zu den Daten wurde eine Methodeneigenschaft angezeigt, die alle Methoden zum Arbeiten mit Daten enthält. Es ist nur eine Methode darin geschrieben - sendData, die oben erwähnt wurde. Es ist an das Absenden des Formulars gebunden und zeigt vorerst nur die Eingabewerte in der Konsole an.
Und der letzte Teil der Komponente ist Stil. Hier werden Stile geschrieben, damit das Formular korrekt angezeigt wird.
Öffnen wir jetzt unsere Anwendung. Vor uns liegt ein Formular, das über die Schaltfläche Senden ausgefüllt und Daten gesendet werden sollten.


Beim Senden wird die Seite nicht neu geladen und die Formularwerte werden nicht zurückgesetzt. Es ist Zeit, in die Browserkonsole zu schauen (Strg + Umschalt + I):

Wenn Sie in der Konsole ungefähr dasselbe sehen, nur mit den von Ihnen angegebenen Werten - Glückwunsch, Sie haben Ihre erste vollwertige Vue-Anwendung geschrieben. Wenn nicht, sollten Sie die Richtigkeit jedes Schritts überprüfen und zu einem positiven Ergebnis kommen.
Lassen Sie die Vue-Anwendung zunächst unverändert und entwickeln den Server auf Node.js weiter, damit die Anwendung Daten austauschen kann.
Weiterentwicklung (Backend)
Zuerst müssen Sie die erforderlichen npm-Pakete für den Serverbetrieb installieren:
npm install -S express morgan mongoose
Der -S-Schalter weist npm an, diese Pakete als Element des Abhängigkeitsarrays zu package.json hinzuzufügen. Die Ausgabe wird eine ähnliche Nachricht sein:

- Express.js ist ein Webanwendungsframework für Node.js zum Erstellen von Webanwendungen und APIs. Es ist minimalistisch und enthält eine große Anzahl von Plug-Ins.
- Morgan - ein Paket zum Protokollieren von HTTP-Anforderungen auf dem Server.
- Mongoose ist ein ORM (Object-Relational Mapping) für MongoDB, das unter Node.js erstellt wurde.
Fügen Sie dann dem Projektstammserver ein weiteres Verzeichnis mit der folgenden Hierarchie hinzu:

server.js - Dies ist der Node.js-Server, der über die Node-Umgebung gestartet wird. Sie können Node ausprobieren, indem Sie hier einfachen Code schreiben, zum Beispiel:
server / server.js console.log('Hello, world!');
Starten Sie dann server.js mit dem Befehl node im Stammverzeichnis des Projekts und geben Sie den Pfad zur Datei und ihren Namen an:
node server/server.js > Hello, world!
Wir werden die Datei server.js löschen und mit der Entwicklung beginnen. Importieren Sie zunächst alle zuvor installierten Pakete (Express, Morgan und Mungo) und initialisieren Sie auch die Express-Anwendung:
server / server.js + const express = require('express'); + const mongoose = require('mongoose'); + const morgan = require('morgan'); + const path = require('path'); + + const app = express();
Wenn Sie noch nie auf const: const gestoßen sind, ersetzt eine der beiden Variablendeklarationsanweisungen (die zweite let) var, den ES6-Standard. Seine Besonderheit ist, dass der einer Variablen zugewiesene Wert nicht geändert werden kann. Für Variablen mit weiteren Variablenwerten wird empfohlen, let zu verwenden.
require () ist eine Funktion der Node.js-Umgebung, die die Möglichkeit implementiert, verschiedene Module zu verbinden, sowohl native als auch npm. Beachten Sie, dass wir das Pfadpaket nicht installiert, sondern importiert haben - es ist bereits in den Umgebungsabhängigkeiten enthalten.
const app = express () - Initialisierung der Express-Anwendung. Als nächstes werden wir mit der App-Variablen arbeiten, dies wird unser Server sein.
Als Nächstes müssen Sie die Einstellungen für unsere Express-Anwendung festlegen. Da diese jedoch klein ist, müssen Sie nur einen Parameter festlegen - den Port. Nehmen Sie zum Beispiel den Wert 3000 (oder einen beliebigen verfügbaren Port). Nachdem wir den Port abgehört haben, d.h. Starten Sie den Server:
server / server.js ... + app.set('port', 3000); + + app.listen(app.get('port'), () => { + console.log(`[OK] Server is running on localhost:${app.get('port')}`); + });
Die set-Methode fügt dem angegebenen Objekt einfach die angegebene Eigenschaft mit dem angegebenen Wert hinzu, die dann durch Zugriff auf den Eigenschaftsnamen mit der get-Methode abgerufen werden kann. Dies ist genau das, was wir tun, wenn wir die Anwendung auf Listen einstellen: app.get ('port') gibt den zuvor festgelegten Wert von 3000 zurück. Nach dem Empfang des Ports gibt es eine Pfeil-Rückruffunktion. Wenn Sie noch nie zuvor auf Pfeilfunktionen gestoßen sind: Die Pfeilfunktion wird als () => {} bezeichnet und ist fast eine vollständige Analogie von function () {}, mit einer Ausnahme: Die Pfeilfunktion hat ein globales Objekt als Kontext für den Aufruf der Funktion (this) (Global) in der Node.js-Umgebung und im Fenster in der Browser-Umgebung) und die übliche Funktion selbst, d.h. Funktion In dieser Situation vereinfacht die Pfeilfunktion einfach die Aufnahme als Wir verwenden dies in keiner Weise. Als Rückruffunktion wird einfach eine Nachricht an die Konsole ausgeführt, die besagt, dass der Server auf localhost: 3000 ausgeführt wird. Wenn Sie $ {...} in die Zeichenfolge schreiben, können Sie einen berechneten Wert einfügen, in unserem Fall den Rückgabewert der Funktion app.get ().
Wenn Sie nun die Adresse localhost: 3000 in Ihrem Browser öffnen, wird die Meldung "Kann nicht erhalten /" angezeigt. Dies bedeutet, dass unser Server gestartet wurde und ordnungsgemäß funktioniert. Später werden wir unsere Vue.js-Anwendung anstelle dieser Nachricht anzeigen lassen, aber vorerst werden wir eine Verbindung zur MongoDB-Datenbank und zur Middleware herstellen:
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 () stellt eine Verbindung zur Datenbank her. Beachten Sie, dass MongoDB selbst aktiv sein muss, bevor Sie erneut eine Verbindung herstellen können. An diese Methode werden zwei Parameter übergeben - die Basisadresse und eine Reihe von Einstellungen in Form eines Objekts. In unserem Fall ist dies die Zeichenfolge "mongodb: // localhost: 27017 / mevn-course" und das Objekt {useNewUrlParser: true}.
useNewUrlParser wird verwendet, um mit MongoDB Version 3.1.0+ zu arbeiten. Wenn Sie aus irgendeinem Grund eine Version unter 3.1.0 verwenden, sollten Sie diesen Parameter nicht angeben.
.then und .catch sind Methoden, die bei Erfüllung bzw. Misserfolg ein Versprechen zurückgeben. Innerhalb dieser Methoden wird eine Rückruffunktion aufgerufen, die das Datenbankobjekt db als Ergebnis des Versprechens für .then und einen Fehler für .catch zurückgibt. Beide Methoden drucken Informationen an die Konsole: entweder über eine erfolgreiche Verbindung oder über einen Fehler.
Mit app.use () wird Middleware für unsere Anwendung installiert. Dies sind Funktionen, die Zugriff auf das Anforderungsobjekt (req), das Antwortobjekt (res) und die nächste Zwischenverarbeitungsfunktion (next) im Anforderungs-Antwort-Zyklus der Anwendung haben. Wir werden als Middleware die in Express integrierten Parser verwenden, die mit Datenanforderungen geliefert werden (in unserem Fall json und urlencodiert), und das Morgan-Paket, das zuvor mit dem Parameter 'dev' installiert wurde, was bedeutet, dass Sie sich im Entwicklungsmodus anmelden. Jetzt kann der Server eingehende Daten mit Anforderungen im JSON- und urlencodierten Format empfangen und alle eingehenden Anforderungen protokollieren. Starten Sie die Anwendung erneut:
Knotenserver / server.js > [OK] Server is running on localhost:3000 > [OK] DB is connected
Wenn wir nun im Browser zur Adresse localhost: 3000 gehen, werden alle Anforderungen in der Konsole protokolliert, in diesem Fall die GET-Anforderung:

Wir werden uns mit der Entwicklung des Record-Modells befassen. Dies ist erforderlich, damit die Daten im gewünschten Format an die Datenbank gesendet werden (dieses Format wird als Schema bezeichnet). Unser Formular aus der Vue-Anwendung sendet Name, E-Mail, Adresse und Geschlecht - all dies kann als Zeichenfolge dargestellt werden. Der Datensatz in der Datenbank sollte also 4 Felder vom Typ "Zeile" enthalten. Erstellen Sie ein Modell:
server / models / 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);
Wir importieren das Mungopaket und setzen die Schema-Variable auf den Wert der Schema-Klasse aus dem Mungo-Paket. Die Notation „const {Schema} = Mungo“ wird in ES6 als Destrukturierung bezeichnet und entspricht „const Schema = Mungo.Schema“. Als Nächstes wird eine Instanz der Schema-Klasse erstellt, deren Parameter ein Objekt mit den Namen der Datensatzeigenschaften und ihren Datentypen ist.
"Module.exports = ..." ist ein Exporteintrag. Das heißt, Wenn wir dieses Modul importieren, lautet das Importergebnis mongoose.model ('Record', Record).
Wenn das Modell erstellt wird, müssen Sie eine API-Routing-Datei erstellen. Als architektonischer Stil der Komponenteninteraktion wird REST verwendet.
Die REST-API definiert eine Reihe von Funktionen, auf die Entwickler Anfragen stellen und Antworten erhalten können. Die Interaktion erfolgt über das HTTP-Protokoll. REST-API-Aufrufmethoden sind CRUD-Methoden (Create, Read, Update, Delete), d.h. GET, POST, PUT, DELETE. Fügen Sie den Code zur Routing-Datei hinzu: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;
Wir importieren das Express-Paket und erstellen das Router-Objekt. Wir importieren auch das Record-Modellmodul, um mit der Datenbank zu interagieren. Im Folgenden wird lediglich das Routing beschrieben. Das Konstrukt async / await ist eine relativ neue Methode zum Schreiben von asynchronem Code. Zuvor wurde ähnlicher Code mit Rückruffunktionen und Versprechungen geschrieben. Dank async / await ähnelt asynchroner Code dem synchronen Code, und in seinem Verhalten treten Merkmale eines solchen Codes auf, die in einigen Situationen sehr nützlich sind, in denen die Verwendung von Versprechungen aus verschiedenen Gründen unpraktisch war.Stattdessen: router.get('/', req, res) => { res.json(Record.find() .then((data) => { return data; })); });
Wir haben: router.get('/', async (req, res) => { res.json(await Record.find()); });
Routermethoden wie .get (), .post (), .put () und .delete () vermitteln dem Server ein Verständnis dafür, wie bestimmte Anforderungen behandelt werden sollen. Innerhalb der Methoden gibt es eine asynchron ausgeführte Rückruffunktion mit zwei Parametern req - dem Anforderungsobjekt und res - dem Antwortobjekt. Mit Ausnahme der POST-Methode wird bei jeder Methode asynchron auf die Datenbank zugegriffen, indem die Methoden des Datensatzmodells verwendet werden, z. B. find (), findById (), findByIdAndUpdate (), findByIdAndRemove (). Dann kommt die Antwort vom Server im JSON-Format, zum Beispiel res.json ({state: 'success'}). Die Verarbeitung der POST-Methode ist unterschiedlich: Zuerst wird eine Instanz der Record-Klasse erstellt, deren Parameter der Anforderungshauptteil ist, der von der Vue-Anwendung stammt, dann wird die Instanz mit der save () -Methode asynchron in der Datenbank gespeichert, und erst dann wird die Antwort im Format gesendet JSON AuchAchten Sie auf die letzten drei Abfragen: Abrufen, Einfügen und Löschen - in der Adresse, die sie haben: ID. Dies bedeutet, dass alles, was nach dem "/" an die Adresse geschrieben wird, als Wert von req.params.id verfügbar ist und als Zeichenfolge dargestellt wird. so können wir per id zugreifen.Vielleicht stellt sich die Frage, mit welcher ID wir auf Datensätze in der Datenbank zugreifen, wenn das Schema nur die Felder Name, E-Mail, Adresse und Geschlecht enthält. Antwort: MongoDB selbst erstellt für jeden Datensatz eine Kennung mit dem Namen _id.Das Modell und das Routing werden geschrieben, es bleibt nur das Importieren des gewünschten Moduls in server.js:server / server.js ... app.use(morgan('dev')); + + app.use('/api/records', require('./routes/records'));
Dieser Eintrag bedeutet, dass das von uns geschriebene Routing mit / api / records beginnt. Das heißt, um einen neuen Datensatz hinzuzufügen, müssen Sie eine POST-Anfrage mit einem Text mit gültigen Daten (Name, E-Mail, Adresse und Geschlecht) an localhost senden : 3000 / api / records.Stellen Sie sicher, dass der Server funktioniert - führen Sie ihn aus und testen Sie die API. Ich benutze dafür Postman. Dies ist ein vollständiges API-Testtool.Eine GET-Anforderung bei localhost : 3000 / api / records gibt jetzt ein leeres Array zurück:
In diesem Fall führen wir eine POST-Anforderung an derselben Adresse aus, in deren Hauptteil wir gültige Daten zum Schreiben in die Datenbank angeben:
Wir sehen, dass die Antwort vom Server im JSON-Format kam wie wir betonten, diese Nachricht{"State": "success"}. Wir führen die vorherige GET-Anfrage erneut aus:
Alles hat sich herausgestellt, Sie können die verbleibenden Operationen an den Daten (UPDATE, DELETE oder GET one) unabhängig testen.Die Entwicklung des Backend-Teils ist abgeschlossen. Es bleibt noch der letzte Schliff - bestimmen Sie die statischen Dateien, die auf localhost angezeigt werden sollen : 3000 /. Fügen Sie den Code hinzu:server / server.js ... app.use('/api/records', require('./routes/records')); + app.use('/', express.static(path.join(__dirname, '../dist')));
Weiterentwicklung (Frontend)
Zurück zur Vue-Anwendung gibt es jetzt eine API, mit der sie interagieren kann. Daher werden wir, ohne Zeit zu verschwenden, die zuvor geschriebene sendData-Methode ändern, aber zuerst mit npm das axios-Paket installieren - npm i -S axios.Ansichten / 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 ist eine Clientbibliothek zum Senden von Anforderungen an einen Server, der Standardversprechen verwendet. Hier verwenden wir das bekannte Konstrukt async / await. Ein Objekt wird an die Axios-Funktion übergeben - eine Reihe von Optionen (URL, Methode, Daten). Wenn die Methode ausgeführt wird, wird die Anforderung gesendet.Führen Sie nun den Befehl npm run build aus. Mit dieser Funktion stellt Vue die fertige Anwendung in dem Verzeichnis dist zusammen, das wir als statische Dateien für den Server angegeben haben: npm run build
Dann starten wir den Server neu und gehen im Browser zu localhost : 3000 /. Genau jetzt wird hier unsere Vue-Anwendung angezeigt. Füllen Sie das Formular aus und senden Sie die Daten, indem Sie auf Senden klicken. Wir schauen uns die Konsole an:
Die Antwort vom Server wird als Daten zurückgegeben. Dies bedeutet, dass der Datensatz hinzugefügt wurde und unsere Anwendung ordnungsgemäß funktioniert.Jetzt machen wir den letzten Schliff in der Anwendung: Weiterleiten beim Senden des Formulars an die Dankesseite; die Möglichkeit, von der Dankesseite zur Hauptseite zu wechseln, Navbar-Links zu löschen und console.log () zu löschen:views / Thanks.vue <template> <div class="thanks"> <h1>Thank you for your record!</h1> + router-link to="/">Home</router-link> </div> </template>
Ansichten / 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> ...
Unsere Vue-Anwendung ist vollständig fertig, wir sammeln sie mit npm run build, wir starten den Server neu, wir überprüfen die Funktionsfähigkeit.Entwicklungsabschluss (Backend)
Es wäre schön, wenn der Server eine Benachrichtigung per E-Mail senden würde, wenn jeder Client jeden neuen Datensatz zur Datenbank hinzufügt. Zu diesem Zweck senden wir den Dienst, um Briefe an Node.js - Nodemailer zu senden. Installieren Sie es: npm install -S Nodemailer. Nachdem Nodemailer installiert ist, fügen Sie server.js folgende Funktionen hinzu: server / route/ 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'}); });
Mal sehen, was hier passiert. Zunächst wird das zuvor installierte Nodemailer-Paket importiert. Zweitens wird die Post-Methode so geändert, dass der Server nicht nur den Datensatz in der Datenbank speichert, sondern auch eine Benachrichtigung an die Mail sendet. Zunächst wird die Ausgabevariable erstellt, in die das HTML-Markup geschrieben wird. Anschließend wird die Transportervariable mit der Methode createTransport des Nodemailer-Objekts erstellt, an das das Objekt übertragen wird - eine Reihe von Optionen zur Authentifizierung des E-Mail-Kontos: Hostname, Port sowie Login und Passwort. Beachten Sie, dass Sie, wenn Sie Google Mail verwenden, zusätzlich zur reinen Authentifizierung zulassen müssen, dass Anwendungen von Drittanbietern das Postfach in Ihren Google Mail-Kontoeinstellungen verwenden. Als nächstes wird die Variable mailOptions erstellt, in die das Objekt geschrieben wird - die Briefoptionen: von wem die Nachricht gesendet wurde, an wen sie gesendet wurde, den Betreff des Briefes und seinen Text. Und endlich,Mit der sendMail-Methode des Transporterobjekts wird der Brief gesendet.Wir starten den Server neu und testen. Wenn die Authentifizierungsinformationen korrekt sind und die Kontoeinstellungen die Verwendung des Postfachs durch Anwendungen von Drittanbietern ermöglichen, wird die Nachricht gesendet und eine Nachricht über das erfolgreiche Senden an die Konsole gesendet. Andernfalls wird der Fehler auch in der Konsole angezeigt. Es sieht aus wie ein erfolgreiches Senden:
Und so ein erfolgloses:
Zusammenfassung
Mit dieser Anwendung wurde die Entwicklung beendet. Was haben wir:- Erfahrung in der Entwicklung von Vue-Anwendungen;
- Erfahrung in der Entwicklung von Node + Express-Servern;
- Erfahrung mit MongoDB;
- Erfahrung mit npm;
- Fähigkeit, Weiterleitungsseiten zu organisieren;
- die Möglichkeit, E-Mail-Newsletter vom Server aus zu organisieren;
- die Fähigkeit, vom Client aus HTTP-Anfragen zu senden und zu empfangen;
- Verständnis der CRUD- und REST-API;