Advertisement
  1. Code
  2. JavaScript
  3. Node

Erstellen Sie Webanwendungen mit Node.js.

Scroll to top
Read Time: 14 min

() translation by (you can also view the original English article)

Einführung

Neben dem Erstellen von APIs eignet sich Node.js hervorragend zum Erstellen von Standard-Webanwendungen. Es verfügt über leistungsstarke Werkzeugs, die den Geschmack von Webentwicklern erfüllen. In diesem Lernprogramm erstellen Sie eine Webanwendung, die als lokale Bibliothek dienen kann.

Während des Erstellens lernen Sie einige Arten von Middleware kennen, erfahren, wie Sie mit dem Senden von Formularen in Node.js umgehen, und Sie können auch auf zwei Modelle verweisen.

Lass uns anfangen.

Loslegen

Installieren Sie zunächst den Expressgenerator auf Ihrer Maschine.

1
npm install express-generator -g

Führen Sie den Befehl express generator aus, um Ihre Anwendung zu generieren.

1
express tutsplus-library --view=pug
1
   create : tutsplus-library
2
   create : tutsplus-library/package.json
3
   create : tutsplus-library/app.js
4
   create : tutsplus-library/public
5
   create : tutsplus-library/routes
6
   create : tutsplus-library/routes/index.js
7
   create : tutsplus-library/routes/users.js
8
   create : tutsplus-library/views
9
   create : tutsplus-library/views/index.pug
10
   create : tutsplus-library/views/layout.pug
11
   create : tutsplus-library/views/error.pug
12
   create : tutsplus-library/bin
13
   create : tutsplus-library/bin/www
14
   create : tutsplus-library/public/javascripts
15
   create : tutsplus-library/public/images
16
   create : tutsplus-library/public/stylesheets
17
   create : tutsplus-library/public/stylesheets/style.css
18
19
   install dependencies:
20
     $ cd tutsplus-library && npm install

21


22
   run the app:
23
     $ DEBUG=tutsplus-library:* npm start

Migrieren Sie nun in Ihre Arbeit, öffnen Sie package.json und stellen Sie die Abhängigkeiten ähnlich wie unten dar.

1
#package.json
2
3
{
4
  "name": "tutsplus-library",
5
  "version": "0.0.0",
6
  "private": true,
7
  "scripts": {
8
    "start": "node ./bin/www"
9
  },
10
  "dependencies": {
11
    "body-parser": "~1.17.1",
12
    "connect-flash": "^0.1.1",
13
    "cookie-parser": "~1.4.3",
14
    "debug": "~2.6.3",
15
    "express": "~4.15.2",
16
    "express-messages": "^1.0.1",
17
    "express-session": "^1.15.5",
18
    "express-validator": "^4.2.1",
19
    "mongoose": "^4.11.12",
20
    "morgan": "~1.8.1",
21
    "pug": "~2.0.0-beta11",
22
    "serve-favicon": "~2.4.2"
23
  }
24
}

Führen Sie den Befehl aus, um die Pakete zu installieren.

1
npm install

Richten Sie die Eingabedatei ein

app.js wurde erstellt, als Sie den Generatorbefehl ausgeführt haben. Sie müssen jedoch eine zusätzliche Konfiguration einrichten. Bearbeiten Sie die Datei so, dass sie wie folgt aussieht.

1
#app.js
2
3
var express = require('express');
4
var path = require('path');
5
var favicon = require('serve-favicon');
6
var logger = require('morgan');
7
var cookieParser = require('cookie-parser');
8
var bodyParser = require('body-parser');
9
const session = require('express-session')
10
const expressValidator = require('express-validator')
11
const flash = require('connect-flash')
12
const mongoose = require('mongoose')
13
14
// 1

15
const genres = require('./routes/genres');
16
const books = require('./routes/books');
17
18
var app = express();
19
20
// 2

21
mongoose.Promise = global.Promise
22
const mongoDB = process.env.MONGODB_URI || 'mongodb://127.0.0.1/tutsplus-library'
23
mongoose.connect(mongoDB)
24
25
// view engine setup

26
app.set('views', path.join(__dirname, 'views'));
27
app.set('view engine', 'pug');
28
29
// uncomment after placing your favicon in /public

30
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));

31
app.use(logger('dev'));
32
app.use(bodyParser.json());
33
app.use(bodyParser.urlencoded({ extended: false }));
34
app.use(cookieParser());
35
app.use(express.static(path.join(__dirname, 'public')));
36
37
// 3

38
app.use(session({
39
  secret: 'secret',
40
  saveUninitialized: true,
41
  resave: true
42
}))
43
44
// 4

45
app.use(expressValidator({
46
  errorFormatter: function(param, msg, value) {
47
    var namespace = param.split('.')
48
    , root = namespace.shift()
49
    , formParam = root
50
51
    while(namespace.length) {
52
      formParam += '[' + namespace.shift() + ']'
53
    }
54
    return {
55
      param : formParam,
56
      msg : msg,
57
      value : value
58
    }
59
  }
60
}))
61
62
// 5

63
app.use(flash())
64
app.use(function (req, res, next) {
65
  res.locals.messages = require('express-messages')
66
  next()
67
})
68
69
// 6

70
app.use('/genres', genres);
71
app.use('/books', books);
72
73
// catch 404 and forward to error handler

74
app.use(function(req, res, next) {
75
  var err = new Error('Not Found');
76
  err.status = 404;
77
  next(err);
78
});
79
80
// error handler

81
app.use(function(err, req, res, next) {
82
  // set locals, only providing error in development

83
  res.locals.message = err.message;
84
  res.locals.error = req.app.get('env') === 'development' ? err : {};
85
86
  // render the error page

87
  res.status(err.status || 500);
88
  res.render('error');
89
});
90
91
module.exports = app;
  1. Sie haben die beiden Routen benötigt, die Sie beim Erstellen dieser Anwendung verwenden werden. Sie werden die Routendatei in Kürze erstellen. Die erforderlichen Routen werden als Werte zwei verschiedenen Variablen zugewiesen, die beim Einrichten der Middleware für Ihre Routen verwendet werden.
  2. Sie setzen Mongoose auf global.Promise. Der Variablen MongoDB wird die MONGODB_URI Ihrer Umgebung oder der Pfad zu Ihrem lokalen Mongo-Server zugewiesen. Diese Variable wird als Argument für die Verbindung zum laufenden MongoDB-Server übergeben.
  3. Sie richten die Sitzungs-Middleware mit express-session ein. Diese Middleware ist wichtig, da in einigen Teilen Ihrer Anwendung Flash-Meldungen angezeigt werden.
  4. Sie richten die Middleware zur Validierung ein. Diese Middleware wird zur Überprüfung der Formulareingabe verwendet, um sicherzustellen, dass Benutzer der Anwendung kein leeres Formular senden. Die Validierung verwendet ein installiertes Paket, express-validator.
  5. Sie richten eine Middleware ein, die sich beim Anzeigen von Flash-Nachrichten als nützlich erweist. Diese Middleware verwendet connect-flash.
  6. Die Routen für die Anwendung sind so eingerichtet, dass sie die von Ihnen benötigte Routendatei verwenden. Anfragen, die auf /genres und /books verweisen, verwenden die Genres- bzw. Buchroutendateien. In diesem Moment haben Sie die Routendateien noch nicht erstellt, aber Sie werden dies bald tun.

Buch- und Genre-Modell

Das Buchmodell verwendet das Mungo-Schema, um zu definieren, wie die Bücher strukturiert werden. Erstellen Sie ein Verzeichnis mit dem Namen models und eine neue Datei mit dem Namen Book.js. So sieht es aus.

1
#models/Book.js
2
3
const mongoose = require('mongoose')
4
mongoose.Promise = global.Promise
5
const Schema = mongoose.Schema
6
7
const bookSchema = Schema({
8
  name: {
9
    type: String,
10
    trim: true,
11
    required: 'Please enter a book name'
12
  },
13
  description: {
14
    type: String,
15
    trim: true
16
  },
17
  author: {
18
    type: String,
19
    trim: true,
20
  },
21
  genre: [{
22
    type: Schema.Types.ObjectId,
23
    ref: 'Genre'
24
  }]
25
})
26
27
module.exports = mongoose.model('Book', bookSchema)

Hier haben Sie vier Felder. Das letzte Feld wird verwendet, um das Genre zu speichern, zu dem jedes Buch gehört. Das Genre-Feld hier verweist auf das Genre-Modell, das als nächstes erstellt wird. Aus diesem Grund wird der Typ auf Schema.Types.ObjectId festgelegt. Hier werden die IDs der einzelnen Genres gespeichert, auf die verwiesen wird. ref gibt das Modell an, auf das Sie verweisen. Beachten Sie, dass das Genre als Array gespeichert wird. Dies bedeutet, dass ein Buch mehr als ein Genre haben kann.

Lassen Sie uns fortfahren und das Genre-Modell erstellen.

1
#models/genre.js
2
3
const mongoose = require('mongoose')
4
mongoose.Promise = global.Promise
5
const Schema = mongoose.Schema
6
7
const genreSchema = Schema({
8
  name: {
9
    type: String,
10
    trim: true,
11
    required: 'Please enter a Genre name'
12
  }
13
})
14
15
module.exports = mongoose.model('Genre', genreSchema)

Für Ihr Genre benötigen Sie nur ein Feld: name.

Genre Index Route und Ansicht

In diesem Tutorial verwenden Sie zwei Routenpfade für Ihr Genre: einen Pfad zum Hinzufügen neuer Genres und einen anderen, der die Genres auflistet, über die Sie verfügen. Erstellen Sie in Ihrem Routenverzeichnis eine Datei mit dem Namen genres.js.

Beginnen Sie damit, dass Sie alle Module benötigen, die Sie verwenden werden.

1
#routes/genres.js
2
3
var express = require('express');
4
var router = express.Router();
5
const mongoose = require('mongoose')
6
const Genre = require('../models/Genre')

Geben Sie als Nächstes die Route ein, die die Indexdatei für Ihre Genres verarbeitet.

1
router.get('/', (req, res, next) => {
2
  const genres = Genre.find({}).exec()
3
    .then((genres) => {
4
      res.render('genres', { genres: genres })
5
  }, (err) => {
6
    throw err
7
  })
8
});

Diese Route wird immer dann aufgerufen, wenn Anfragen an /genres gestellt werden. Hier rufen Sie die Suchmethode für Ihr Genre-Modell auf, um alle erstellten Genres abzurufen. Diese Genres werden dann in einer Vorlage namens genres gerendert. Lassen Sie uns fortfahren und das erstellen, aber aktualisieren Sie zuerst Ihr layout.pug so, dass es so aussieht:

1
#views/layout.pug
2
3
doctype html
4
html
5
  head
6
    title= title
7
    link(rel='stylesheet', href='/stylesheets/style.css')
8
    link(rel='stylesheet', href='https://bootswatch.com/paper/bootstrap.css')
9
    script(src='https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js')
10
    script(src='https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js')
11
  body
12
    .container-fluid
13
      block header
14
        nav.navbar.navbar-inverse
15
          .container-fluid
16
            .navbar-header
17
              button.navbar-toggle.collapsed(type='button', data-toggle='collapse', data-target='#bs-example-navbar-collapse-2')
18
                span.sr-only Toggle navigation
19
                span.icon-bar
20
                span.icon-bar
21
                span.icon-bar
22
              a.navbar-brand(href='#') Local Library
23
            #bs-example-navbar-collapse-2.collapse.navbar-collapse
24
              ul.nav.navbar-nav.navbar-right
25
                li
26
                  a(href='/books') View Books
27
                li
28
                  a(href='/books/add') Add New Book
29
                li
30
                  a(href='/genres') View Genres
31
                li
32
                  a(href='/genres/add') Add New Genre
33
        block content

Dies gibt Ihren Ansichten eine schöne Struktur, um die Navigation zu erleichtern. Erstellen Sie nun eine Ansichtsdatei mit dem Namen genre.pug. In dieser Datei durchlaufen Sie die erstellten Genres und geben jedes Genre in einer ungeordneten Liste aus.

So sollte die Datei aussehen.

1
#views/genres.pug
2
3
extends layout
4
5
block content
6
  h1 Genre
7
  ul.well.well-lg
8
    each genre, i in genres
9
      li.well.well-sm
10
        p #{genre.name}

Neue Genre-Routen hinzufügen und anzeigen

Kehren Sie zu Ihren routes/genres.js zurück, um die Routen hinzuzufügen, die für die Erstellung neuer Genres verwendet werden.

1
#routes/genres.js
2
3
// 1

4
router.get('/add', (req, res, next) => {
5
  res.render('addGenre')
6
})
7
8
// 2

9
router.post('/add', (req, res, next) => {
10
  req.checkBody('name', 'Name is required').notEmpty()
11
12
  const errors = req.validationErrors()
13
14
  if (errors) {
15
    console.log(errors)
16
    res.render('addgenres', { genre, errors })
17
  }
18
19
  const genre = (new Genre(req.body)).save()
20
    .then((data) => {
21
      res.redirect('/genres')
22
    })
23
    .catch((errors) => {
24
      console.log('oops...')
25
      console.log(errors)
26
    })
27
})
28
29
// 3

30
module.exports = router;
  1. Die Aufgabe dieses Routers besteht darin, einfach die Seite zum Hinzufügen neuer Routen anzuzeigen. Dieser Router wird aufgerufen, wenn Anforderungen an /genres/add path gestellt werden.
  2. Dieser Router übernimmt die Übermittlung des Formulars. Wenn das Formular gesendet wird, prüfen wir, ob der Benutzer einen Namen eingegeben hat. Wenn kein Name eingegeben wird, wird die Seite neu gerendert. Wenn die Überprüfungen noch nicht abgeschlossen sind, wird das Genre gespeichert und der Benutzer wird zur Seite /genres weitergeleitet.
  3. Das Modul wird als Router exportiert.

Jetzt können Sie die Seite zum Hinzufügen eines neuen Genres erstellen.

1
#views/addGenre.pug
2
3
extends layout
4
5
block content
6
  .row
7
    .col-md-12
8
      h1 Add Book
9
      form(method="POST", action="/genres/add")
10
        .form-group
11
          label.col-lg-2.control.label Name
12
          .col-lg-10
13
            input.form-control(type="text", name='name')
14
        .form-group
15
          .col-lg-10.col-lg-offset-2
16
            input.button.btn.btn-primary(type='submit', value='Submit')
17
      
18
      if errors
19
        ul
20
          for error in errors
21
            li!= error.msg

Bücher Routen und Ansicht

Erstellen Sie eine neue Routendatei für Bücher und nennen Sie sie books.js. Wie Sie es zuvor mit dem Genre getan haben, benötigen Sie zunächst die erforderlichen Module.

1
#routes/books.js
2
3
var express = require('express');
4
var router = express.Router();
5
const mongoose = require('mongoose')
6
const Book = require('../models/Book')
7
const Genre = require('../models/Genre')

Richten Sie als Nächstes den Router für die Anzeige aller in der Bibliothek gespeicherten Bücher ein. Versuchen Sie das selbst auf die Art und Weise, wie Sie das Genre einrichten. Sie können jederzeit zurückschauen, um Korrekturen vorzunehmen.

Ich denke, Sie haben das ausprobiert - so sollte es aussehen.

1
router.get('/', (req, res, next) => {
2
  const books = Book.find({}).exec().then((books) => {
3
    res.render('books', { books: books })
4
  }, (err) => {
5
    throw err
6
  })
7
});

Wenn dieser Router aufgerufen wird, wird eine Anforderung gestellt, alle in der Datenbank gespeicherten Bücher zu finden. Wenn alles gut geht, werden die Bücher auf der Seite /books angezeigt, andernfalls wird ein Fehler ausgegeben.

Sie müssen eine neue Datei erstellen, um alle Bücher anzuzeigen. So sollte sie aussehen.

1
#views/books.pug
2
3
extends layout
4
5
block content
6
  h1 Books
7
  ul.well.well-lg
8
    each book, i in books
9
      li.well.well-sm
10
        a(href=`/books/show/${book.id}`) #{book.name}
11
        p= book.description

Sie durchlaufen einfach die zurückgegebenen Bücher und geben den Namen und die Beschreibung jedes Buches mithilfe einer ungeordneten Liste aus. Der Name des Buches verweist auf die einzelne Seite des Buches.

Neue Buchrouten hinzufügen und anzeigen

Der nächste von Ihnen eingerichtete Router übernimmt das Hinzufügen neuer Bücher. Hier werden zwei Router verwendet: Einer rendert einfach die Seite und ein anderer übernimmt die Übermittlung des Formulars.

So sehen die Router aus.

1
router.get('/add', (req, res, next) => {
2
  const genres = Genre.find({}).exec()
3
    .then((genres) => {
4
      res.render('addBooks', { genres })
5
    })
6
    .catch((err) => {
7
      throw err
8
    })
9
})
10
11
router.post('/add', (req, res, next) => {
12
  req.checkBody('name', 'Name is required').notEmpty()
13
  req.checkBody('description', 'Description is required').notEmpty()
14
  req.checkBody('genre', 'Genre is required').notEmpty
15
16
  const errors = req.validationErrors()
17
18
  if (errors) {
19
    console.log(errors)
20
    res.render('addBooks', { book, errors })
21
  }
22
23
  const book = (new Book(req.body)).save()
24
    .then((data) => {
25
      res.redirect('/books')
26
    })
27
    .catch((errors) => {
28
      console.log('oops...')
29
    })
30
})

Im ersten Router wird die Seite /addBooks angezeigt. Dieser Router wird aufgerufen, wenn eine Anforderung an /add path gestellt wird. Da hinzugefügte Bücher Genres haben sollen, möchten Sie die Genres anzeigen, die in der Datenbank gespeichert wurden.

1
  const genres = Genre.find({}).exec()
2
      .then((genres) => {

Der obige Code findet alle Genres in Ihrer Datenbank und gibt sie in den variablen Genres zurück. Auf diese Weise können Sie die Genres durchlaufen und als Kontrollkästchen anzeigen.

Der zweite Router übernimmt die Übermittlung des Formulars. Zunächst überprüfen Sie den Hauptteil der Anforderung, um sicherzustellen, dass einige Felder nicht leer sind. Hier bietet sich die in app.js festgelegte express-validator-Middleware an. Bei Fehlern wird die Seite neu gerendert. Wenn keine vorhanden sind, wird die neue Buchinstanz gespeichert und der Benutzer wird zur Seite /books weitergeleitet.

Lassen Sie uns fortfahren und die Ansichten dafür erstellen.

Erstellen Sie eine neue Ansichtsdatei mit dem Namen addBooks.pug. Beachten Sie, dass der Name der Ansicht mit dem ersten Parameter übereinstimmt, der res.render zugewiesen wurde. Dies liegt daran, dass Sie eine Vorlage rendern. Während der Umleitung übergeben Sie einfach den Pfad, zu dem Sie umleiten möchten, wie Sie es mit res.redirect('/books') getan haben.

Nachdem dies festgestellt wurde, sollten die Ansichten wie folgt aussehen.

1
#views/addBooks.pug
2
3
extends layout
4
5
block content
6
  .row
7
    .col-md-12
8
      h1 Add Book
9
      form(method="POST", action="/books/add")
10
        .form-group
11
          label.col-lg-2.control-label Name
12
          .col-lg-10
13
            input.form-control(type="text", name='name')
14
        .form-group
15
          label.col-lg-2.control-label Author
16
          .col-lg-10
17
            input.form-control(type="text", name='author')
18
        .form-group
19
          label.col-lg-2.control-label Book Description
20
          .col-lg-10
21
            textarea#textArea.form-control(rows='3', name='description')
22
        .form-group
23
          label.col-lg-2.control-label Genre
24
          .col-lg-10
25
            for genre in genres
26
              .checkbox
27
                input.checkbox(type='checkbox', name='genre', id=genre._id, value=genre._id, checked=genre.checked)
28
                label(for=genre._id) #{genre.name}
29
        .form-group
30
          .col-lg-10.col-lg-offset-2
31
            input.button.btn.btn-primary(type='submit', value='Submit')
32
      
33
      if errors
34
        ul
35
          for error in errors
36
            li!= error.msg

Das Wichtigste dabei ist die Formaktion und -methode. Wenn Sie auf die Schaltfläche "Senden" klicken, senden Sie eine POST-Anfrage an /books/add. Eine andere Sache - Sie durchlaufen erneut die Sammlung der zurückgegebenen Genres und zeigen jedes einzelne an.

Buch Route und Ansicht anzeigen

Lassen Sie uns in die Route eintauchen, um die an jede Buchseite gestellten Anfragen zu bearbeiten. Während Sie dort sind, ist es wichtig, auch Ihr Modul zu exportieren.

1
#routes/books.js
2
3
router.get('/show/:id', (req, res, next) => {
4
  const book = Book.findById({ _id: req.params.id })
5
  .populate({
6
    path: 'genre',
7
    model: 'Genre',
8
    populate: {
9
      path: 'genre',
10
      model: 'Book'
11
    }
12
  })
13
  .exec()
14
    .then((book) => {
15
      res.render('book', { book })
16
    })
17
    .catch((err) => {
18
      throw err
19
    })
20
})
21
22
module.exports = router;

Hier passiert keine Magie.

Erstens müssen Anforderungen an diesen Router eine ID haben: die ID des Buches. Diese ID wird aus den Parametern der Anforderung mit req.params.id abgerufen. Dies wird verwendet, um das spezifische Buch zu identifizieren, das aus der Datenbank abgerufen werden soll, da die IDs eindeutig sind. Wenn das Buch gefunden wurde, wird der Genrewert des Buches mit allen Genres gefüllt, die in dieser Buchinstanz gespeichert wurden. Wenn alles gut geht, wird die Buchansicht gerendert, andernfalls wird ein Fehler ausgegeben.

Lassen Sie uns die Ansicht für ein Buch erstellen. So sollte es aussehen.

1
block content
2
  .well.well-lg
3
    h1 #[strong Name:] #{book.name}
4
    ul
5
      li #[strong Description:] #{book.description}
6
      li #[strong Author]: #{book.author}
7
      li #[strong Genre:]
8
        each genre in book.genre
9
          #{genre.name}
10
          |,

Sie können Ihren Knotenserver starten, indem Sie Folgendes ausführen:

1
DEBUG=tutsplus-library:* npm start

Abschluss

Jetzt wissen Sie, wie Sie in Node.js eine Standard-Webanwendung erstellen, nicht nur eine einfach zu erledigende App. Sie konnten die Formularübermittlung durchführen, auf zwei Modelle verweisen und Middleware einrichten.

Sie können noch weiter gehen, indem Sie die Anwendung erweitern. Versuchen Sie, die Möglichkeit zum Löschen eines Buches hinzuzufügen. Fügen Sie zuerst eine Schaltfläche zur Show-Seite hinzu, gehen Sie dann zu den Routendateien und fügen Sie dazu einen Router hinzu. Beachten Sie, dass dies eine POST-Anforderung sein wird.

Sie können sich auch weitere Funktionen vorstellen, die Sie der Anwendung hinzufügen können. Ich hoffe, dass es Ihnen gefallen hat.

Advertisement
Did you find this post useful?
Want a weekly email summary?
Subscribe below and we’ll send you a weekly email summary of all new Code tutorials. Never miss out on learning about the next big thing.
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.