Bortsett fra å bygge APIer, er Node.js perfekt for å bygge standard webapplikasjoner. Den har kraftige verktøy for å møte smaken av webutviklere. I denne opplæringen vil du bygge et webprogram som kan fungere som et lokalt bibliotek.
Mens du bygger, lærer du om noen typer mellomvare, du vil se hvordan du håndterer skjemainnlevering i Node.js, og du vil også kunne referere til to modeller.
La oss komme i gang.
Start med å installere ekspressgeneratoren på maskinen din.
npm installere ekspress-generator -g
Kjør uttrykkgenerator-kommandoen for å generere søknaden din.
express tutsplus-bibliotek - view = pug
opprett: tutsplus-bibliotek opprette: tutsplus-bibliotek / package.json opprette: tutsplus-bibliotek / app.js opprette: tutsplus-bibliotek / offentlig opprettelse: tutsplus-bibliotek / ruter oppretter: tutsplus-bibliotek / ruter / index.js opprette: tutsplus-bibliotek / ruter / users.js opprette: tutsplus-bibliotek / visninger skape: tutsplus-bibliotek / visninger / index.pug opprette: tutsplus-bibliotek / visninger / layout.pug opprette: tutsplus-bibliotek / visninger / error.pug opprette : tutsplus-bibliotek / public / images create: tutsplus-bibliotek / offentlige / stilark oppretter: tutsplus-bibliotek / bin / www create: tutsplus-bibliotek / offentlige / stylesheets / style.css installasjonsavhengigheter: $ cd tutsplus-bibliotek && npm installer kjøre appen: $ DEBUG = tutsplus-bibliotek: * npm start
Nå migrere til arbeidet ditt, åpne package.json, og gjør avhengighetene likt det jeg har under.
# package.json "name": "tutsplus-bibliotek", "versjon": "0.0.0", "privat": sant, "skript": "start": "node ./bin/www", "avhengighet": "body-parser": "~ 1.17.1", "connect-flash": "^ 0.1.1", "cookie-parser": "~ 1.4.3", "debug" 2.6.3 "," Express ":" ~ 4.15.2 "," Express-messages ":" ^ 1.0.1 "," Express-session ":" ^ 1.15.5 "," Express-validator ":" ^ 4.2.1 "," mongoose ":" ^ 4.11.12 "," morgan ":" ~ 1.8.1 "," pug ":" ~ 2.0.0-beta11 "," tjener-favicon ":" ~ 2.4. 2 "
Kjør kommandoen for å installere pakkene.
npm installasjon
app.js
ble opprettet da du kjørte generatorkommandoen; Du må imidlertid konfigurere ekstra konfigurasjon. Rediger filen for å se ut som jeg har under.
# app.js var express = krever ('express'); var sti = krever ('sti'); var favicon = krever ('server-favicon'); var logger = krever ('morgan'); var cookieParser = krever ('cookie-parser'); var bodyParser = krever ('body-parser'); const session = krever ('express-session') const expressValidator = krever ('express-validator') const flash = krever ('connect-flash') const mongoose = krever ('mongoose') // 1 const genrer = krever ' ./routes/genres'); const bøker = krever ('./ ruter / bøker'); var app = express (); // 2 mongoose.Promise = global.Promise const mongoDB = process.env.MONGODB_URI || 'mongodb: //127.0.0.1/tutsplus-library' mongoose.connect (mongoDB) // se motoroppsett app.set ('views', path.join (__ dirname, 'views')); app.set ('view engine', 'pug'); // uncomment etter at du har lagt inn favicon i / offentlig //app.use(favicon(path.join(__dirname, 'public', 'favicon.ico'))); app.use (logger ( 'dev')); app.use (bodyParser.json ()); app.use (bodyParser.urlencoded (extended: false)); app.use (cookieParser ()); app.use (express.static (path.join (__ dirname, 'public'))); // 3 app.use (session (secret: 'secret', saveUnitialized: true, resave: true)) // 4 app.use (expressValidator (errorFormatter: funksjon (param, msg, verdi) var namespace = param.split ('.'), root = namespace.shift (), formParam = root mens (namespace.length) formParam + = '[' + namespace.shift () + ']' return param: formParam, msg: msg, value: value)) // 5 app.use (flash ()) app.use (funksjon (req, res, neste) res.locals.messages = krever ('express-messages') neste ()) // 6 app.use ('/ genres', sjangere); app.use ('/ bøker', bøker); // fangst 404 og videre til feilbehandler app.use (funksjon (req, res, neste) var err = ny feil ('ikke funnet'); err.status = 404; neste (err);); // feilbehandler app.use (funksjon (feil, req, res, neste) // sett lokalbefolkningen, bare gi feil i utviklingen res.locals.message = err.message; res.locals.error = req.app.get ('env') === 'utvikling'? err: ; // gjør feil side res.status (err.status || 500); res.render ('error');); module.exports = app;
global.Promise
. Variabelen MongoDB
er tildelt MONGODB_URI
av miljøet eller banen til din lokale mongo-server. Denne variabelen er bestått som et argument for å koble til den løpende MongoDB-serveren.ekspress-session
. Denne mellomprogramvaren er viktig da du vil vise flashmeldinger i enkelte deler av søknaden din.express-validator
.koble-flash
.Bokmodellen vil bruke Mongoose Schema til å definere hvordan bøkene skal struktureres. Opprett en katalog som heter modeller, og en ny fil som heter Book.js. Slik ser det ut.
# modeller / Book.js const mongoose = krever ('mongoose') mongoose.Promise = global.Promise const Schema = mongoose.Schema const bookSchema = Schema (navn: type: String, trim: true, required: 'Vennligst skriv inn et boknavn ', beskrivelse: type: String, trim: true, forfatter: type: String, trim: true,, genre: [type: Schema.Types.ObjectId, ref:' Genre '] ) module.exports = mongoose.model ('Book', bookSchema)
Her har du fire felt. Det siste feltet brukes til å lagre sjangeren hver bok tilhører. Genrefeltet her refererer til genre-modellen, som vil bli opprettet neste. Det er derfor typen er satt til Schema.Types.ObjectId
, som er hvor ids for hver referert sjanger vil bli lagret. ref
angir hvilken modell du refererer til. Merk at sjangeren er lagret som en matrise, noe som betyr at en bok kan ha mer enn én sjanger.
La oss fortsette å lage sjangre-modellen.
# modeller / genre.js const mongoose = krever ('mongoose') mongoose.Promise = global.Promise const Schema = mongoose.Schema const genreSchema = Skjema (navn: type: String, trim: true, required: 'Vennligst skriv inn et genre navn ') module.exports = mongoose.model (' Genre ', genreSchema)
For sjangeren din trenger du bare ett felt: Navn
.
For denne opplæringen vil du benytte to ruterbaner for sjangeren din: en sti for å legge til nye sjangere, og en annen som viser de sjangrene du har. Lag en fil i rutekartet ditt genres.js.
Begynn med å kreve alle modulene du vil benytte deg av.
# ruter / genres.js var express = krever ('express'); var router = express.Router (); const mongoose = krever ('mongoose') const Genre = krever ('... / modeller / sjanger')
Deretter slippe ruten som håndterer indeksfilen for sjangrene dine.
router.get ('/', (req, res, neste) => const genres = Genre.find () .exec () .then ((genres) => res.render ('genres' sjangre: sjangre), (err) => kaste err));
Denne ruten blir kalt når forespørsler gjøres til / sjangere. Her kaller du søkemetoden på sjangre-modellen for å få tak i alle sjangrene som er opprettet. Disse sjangrene blir deretter gjengitt på en mal som heter sjangere. La oss gå videre og skape det, men først oppdaterer du layout.pug å se slik ut:
# views / layout.pug doctype html html head title = tittellink (rel = 'stylesheet', href = "/ stylesheets / style.css") lenke (rel = 'stylesheet', href = "https://bootswatch.com / src / ' .bootstrapcdn.com / bootstrap / 3.3.7 / js / bootstrap.min.js ') body .container-fluid block header nav.navbar.navbar-inverse .container-fluid .navbar-header button.navbar-toggle.collapsed ( type = 'knapp', data-bytte = "kollaps", data-target = "# bs-example-navbar-collapse-2") span.sr-only Bytt navigasjon span.icon-bar span.icon-bar span. ikon-bar a.navbar-merke (href = '#') Lokalt bibliotek # bs-eksempel-navbar-collapse-2.collapse.navbar-collapse ul.nav.navbar-nav.navbar-høyre li a (href = ' / bøker ') Se bøker li a (href =' / books / add ') Legg til ny bok li a (href =' / genres ') Vis sjangere li a (href =' / genres / add ') Legg til nytt genreblokk innhold
Dette gir dine synspunkter en fin struktur for å hjelpe navigasjonen. Lag nå en visningsfil som heter genre.pug. I denne filen slår du gjennom sjangrene opprettet og utfører hver sjanger i en uordnet liste.
Slik ser filen ut.
# views / genres.pug utvider layoutblokk innhold h1 Sjanger ul.well.well-lg hver sjanger, jeg i sjangre li.well.well-sm p # genre.name
Gå tilbake til din ruter / genres.js å legge til ruter som håndterer opprettelsen av nye sjangere.
# ruter / genres.js // 1 router.get ('/ add', (req, res, neste) => res.render ('addGenre')) // 2 router.post ('/ add' (req, res, next) => req.checkBody ('navn', 'Navn kreves'). notEmpty () const errors = req.validationErrors () hvis (feil) console.log (feil) res.render (genre, feil) const genre = (ny sjanger (req.body)). lagre () .then ((data) => res.redirect ('/ genres')) .catch ((feil) => console.log ('oops ...') console.log (feil))) // 3 module.exports = router;
Nå kan du gå videre og lage siden for å legge til en ny sjanger.
# views / addGenre.pug utvider layoutblokk innhold .row .col-md-12 h1 Legg til bokform (metode = "POST", action = "/ genres / add") .form-gruppe label.col-lg-2. control.label Navn .col-lg-10 input.form-control (type = "tekst", navn = "navn") .form-gruppe .col-lg-10.col-lg-offset-2 input.button. btn.btn-primary (type = 'submit', verdi = "Send") hvis feil ul for feil i feil li! = error.msg
Opprett en ny rutefil for bøker, og oppgi navnet books.js. Som du gjorde tidligere med sjangeren, start med å kreve de nødvendige modulene.
# ruter / books.js var express = krever ('express'); var router = express.Router (); const mongoose = krever ('mongoose') const Book = krever ('... / models / Book') const Genre = krever ('... / modeller / Genre')
Deretter konfigurerer du ruteren for å vise alle bøkene som er lagret i biblioteket. Prøv det på egen hånd i den måten du oppretter det av sjangeren; Du kan alltid sjekke tilbake for å foreta rettelser.
Jeg antar at du prøvde at ut her er hvordan det skal se ut.
router.get ('/', (req, res, neste) => const books = Book.find () .exec (). deretter ((bøker) => res.render ('bøker' bøker: bøker), (err) => kaste err));
Når denne ruteren kalles, blir det bedt om å finne alle bøkene som er lagret i databasen. Hvis alt går bra, vises bøkene på / bøker side, ellers blir en feil kastet.
Du må opprette en ny fil for å vise alle bøker, og her er hvordan det skal se ut.
# visninger / books.pug utvider layoutblokk innhold h1 Bøker ul.well.well-lg hver bok, jeg i bøker li.well.well-sm a (href = '/ books / show / $ book.id') # book.name p = book.description
Du slår bare gjennom bøkene som returneres og skriver ut navnet og beskrivelsen av hver bok ved hjelp av en uordnet liste. Bokens navn peker på den enkelte side av boken.
Den neste ruteren du setter opp håndterer tillegg av nye bøker. To rutere vil bli brukt her: en vil bare gjøre siden, og en annen vil håndtere skjemaets innsendelse.
Slik ser ruterne ut.
router.get ('/ add', (req, res, neste) => const genres = Genre.find () .exec () .then ((genres) => res.render ('addBooks' genres)) .catch ((err) => kaste err)) router.post ('/ add', (req, res, next) => req.checkBody ('navn', 'Navn er nødvendig "). notEmpty () req.checkBody ('beskrivelse', 'Beskrivelse er nødvendig'). notEmpty () req.checkBody ('genre', 'Genre er påkrevet'). ikkeEmpty const errors = req.validationErrors () hvis (feil) console.log (feil) res.render ('addBooks', bok, feil) const book = (ny bok (req.body)). lagre () .then ((data) => res.redirect ('/ books')) .catch ((feil) => console.log ('oops ...')))
I den første ruteren viser du / addBooks side. Denne ruteren kalles når en forespørsel blir gjort til /Legg til sti. Siden bøkene som er lagt til, skal ha sjangere, vil du vise sjangrene som er lagret i databasen.
const genres = Genre.find () .exec () .then ((sjangre) =>
Koden ovenfor finner alle sjangrene i databasen din og returnerer dem i variabel sjangrene. Med dette vil du kunne gå gjennom sjangrene og vise dem som kryssboksene.
Den andre ruteren håndterer innlevering av skjemaet. Først sjekker du kroppen på forespørselen for å sikre at noen felt ikke er tomme. Det er her express-validator
middleware du satt inn app.js kommer hendig. Hvis det er feil, blir siden gjengitt. Hvis det ikke er noen, lagres den nye boken-forekomsten og brukeren blir omdirigert til siden / bøker.
La oss gå videre og skape synspunkter for dette.
Opprett en ny visningsfil som heter addBooks.pug. Merk at navnet på visningen samsvarer med den første parameteren som er gitt til res.render. Dette skyldes at du gjør en mal. Under omadressering passerer du bare banen du vil omdirigere til, som du gjorde med res.redirect ( '/ bøker')
.
Å ha etablert det, her er hva utsikten skal se ut.
# views / addBooks.pug utvider layoutblokkinnhold .row .col-md-12 h1 Legg til bokform (metode = "POST", action = "/ bøker / legg til") .form-gruppe label.col-lg-2. kontrolletikett Navn .col-lg-10 input.form-control (type = "tekst", navn = "navn") .form-gruppe label.col-lg-2.control-label Forfatter .col-lg-10 input.form-control (type = "tekst", navn = "forfatter") .form-gruppe label.col-lg-2.control-label Bokbeskrivelse .col-lg-10 textarea # textArea.form-control (rader = '3', navn = "beskrivelse") .form-gruppe label.col-lg-2.control-label Genre .col-lg-10 for sjanger i sjangre .checkbox input.checkbox (type = 'avkrysningsboks' = "genre", id = genre._id, verdi = genre._id, merket = genre.checked) etikett (for = genre._id) # genre.name .form-gruppe .col-lg-10.col- lg-offset-2 input.button.btn.btn-primary (type = 'submit', verdi = "Send") hvis feil ul for feil i feil li! = error.msg
Det viktige å merke seg her er form handling og metode. Når send-knappen er klikket, lager du en POST forespørsel til / bøker / add. En annen ting-igjen du går gjennom samlingen av sjangere returneres og viser hver av dem.
La oss slippe inn ruten for å håndtere forespørslene til hver bøkerside. Mens du er der, er det viktig å eksportere modulen din også.
# ruter / books.js router.get ('/ show /: id', (req, res, neste) => const book = Book.findById (_id: req.params.id) .populate : 'genre', modell: 'Genre', populere: sti: 'sjanger', modell: 'Book') .exec () .then ((bok) => res.render bok)) .catch ((err) => kaste err)) module.exports = router;
Ingen magi skjer her.
Først må forespørsler til denne ruteren ha et id: bokens id. Dette id er hentet fra parametrene til forespørselen ved hjelp av req.params.id
. Dette brukes til å identifisere den spesifikke boken som skal hentes fra databasen, da ids er unike. Når boken er funnet, er genreverdien av boken befolket med alle sjangrene som er lagret i denne bokseksemplen. Hvis alt går bra, blir bokvisningen gjengitt, ellers blir en feil kastet.
La oss lage visningen for en bok. Slik ser det ut.
blokker innhold .well.well-lg h1 # [strong Name:] # book.name ul li # [strong Beskrivelse:] # book.description li # [strong Forfatter]: # book.author li # [sterk sjanger:] hver sjanger i book.genre # genre.name |,
Du kan starte nodeserveren din ved å kjøre:
DEBUG = tutsplus-bibliotek: * npm start
Nå vet du hvordan du bygger en standard webapplikasjon i Node.js, ikke bare en enkel å gjøre app. Du var i stand til å håndtere skjema innsending, referanse to modeller, og sette opp noen mellomvare.
Du kan gå videre ved å utvide programmet - prøv å legge til muligheten til å slette en bok. Først legger du til en knapp på visningssiden, og deretter går du til rutefilene og legger til en ruter for dette. Legg merke til at dette skal være en POST be om.
Du kan også tenke på flere funksjoner å legge til i programmet. jeg håper du likte det.