首頁 web前端 js教程 如何快速使用node.js進行網頁開發

如何快速使用node.js進行網頁開發

Jun 30, 2018 pm 03:47 PM
node node.js web開發

本篇文章主要介紹了快速使用node.js進行web開發詳解,內容挺不錯的,現在分享給大家,也給大家做個參考。

首先關於node.js的學習,這裡推荐一本比較好的教程,nodejs web開發指南,該書通俗易懂地將node.js語言特性講解完之後,又從一個專案角度帶領讀者使用node.js學習web開發。相信這是一個比較好的學習模式和過程。由於這本書是2012年出的,書中的一個web教學計畫是發展一個微博。從2012到現在,node.js及其生態環境發生了很大改變,所以關於該書的學習如果照著書本顯然是過於陳舊的。到目前為止,node.js的web開發框架已經升級到了Express4.12.1,對於MongoDB的操作更多是使用mongoose這個物件模型,而不是之前mongoDB 官方提供的原生node.js的API,所以本文將基於nodejsV0 .1033 MongoDBV3.0.2 Jade1.9.2 mogooseV4.0.1來重構該書中的微博項目,這個組合也是目前最新的使用node.js進行web開發的常用組合之一,如果需要入門使用node.js進行web開發,正在學習nodejs web開發指南的和想快速了解node.js web開發模式的朋友,相信本文是有一定幫助意義的。

1.express框架安裝

1)在node命令列模式下輸入以下命令

npm install -g express
登入後複製

該指令在全域環境下安裝express框架,在安裝完這一步之後,並不能直接使用express指令來產生express項目,需要再安裝一個express項目產生器,在express2.X的版本中是不需要的,express4.X版本之後將項目生成器和express本身分離了出來,如果不安裝express-generator這個生成器就使用express命令來生成項目,會遇到報express不是內部或外部命令這個錯誤,這是要注意的地方,nodejs web開髮指南原書中是沒有安裝express-generator這一步的。

2)安裝express-generator

npm install -g express-generator
登入後複製

#3)產生一個專案

cd ..
mkdir microblog
cd microblog
express micorblog
登入後複製

#這裡隨意在硬碟某個目錄下建立一個microblog的資料夾,進入這個資料夾,然後使用express microblog指令建立了一個microblog的express專案。

生成架構如下:

其中app.js是專案入口文件,package.json是npm 套件管理文件,bin資料夾裡面的www. js放一些全域設定項以及命令列配置等。 public 資料夾是用來存放專案靜態檔案目錄如js,css以及圖片,routes資料夾是用來存放路由監聽的程式碼相關檔案。 views資料夾用來存放範本文件,這裡要注意的是express4.X使用jade作為專案的預設範本引擎,而在原書中是使用ejs作為範本引擎的,所以這裡預設產生的是jade檔案。無可否認ejs是要簡單些,但是原理都是一樣的,我們使用jade作為開發的模板引擎。

4)啟動專案並查看

cd microblog
npm install
npm start
登入後複製

#進入到microblog資料夾,安裝專案所需相關模組(根據pacakge.json檔案) ,然後啟動項目,這時候打開瀏覽器查看項目輸入地址localhost:3000,結果如下說明一切正常,

到目前為止,我們已經擁有了一個在瀏覽器中運作的web項目雛形。以下進行開發,原書中的微博專案的主要功能是使用者能夠註冊登錄,權限控制並讓使用者發布微博在使用者個人主頁和專案首頁分別顯示,這些功能完整版代碼會提供,由於篇幅原因,這裡以使用者註冊登入模組來說明如何進行一個完整流程的web開發。

2.頁面佈局

依照web開發流程,我們先來建立一個專案首頁,專案首頁是由版面配置檔layout.jade和內容檔index.jade組成,關於的jade的學習,這裡提供兩個地址,對於以前使用過類似模板引擎如smarty,razor等的,可以看看文檔就能夠上手做了,基本原理都是大同小異。

開啟views文件,將layout.jade文件程式碼改寫如下:

#
doctype html
html
 head
  title= title
  link(rel='stylesheet', href='/stylesheets/style.css')
 body
   nav.header
     ul.list
       li.logo
         a(href='/') Microblog
       li
         a(href='/') 首页
       li
         a(href='/login') 登录
       li
         a(href='/reg') 注册
    p.container
      block content
      hr
      footer.footer
        p
          a(href='http://myzhibie.coding.io') myzhibie
          | @2015
登入後複製

需要注意父級元素和子元素的換行之間縮進,jade是利用縮進來區別程式碼層級的。

首頁內容檔案index.jade

extends layout
block content
  main.main
    section.intro
      if message
        h3.indexmes #{message}
      //如果用户登录或者注册成功并且没有在登录状态下点击注册或者登录
      if success&&user
        h1.welcome #{success},欢迎 #{user} 来到 Microblog
      else if !success&&user
        h1.welcome 欢迎 #{user} 来到 Microblog
      else
        h1.welcome 欢迎来到 Microblog
      h3.tech Microblog是一个基于Node.js,使用express4.12.1,jade1.9.2以及MongoDB搭建起来的微博系统,是对Node.js开发指南一书中教学项目的重构。
      p.btnlist
        if user
          a.login(href='/logout') 退出
          a.userlink(href='/users/#{user}') 发表文章
        else
          a.login(href='/login') 登录
          a.register(href='/reg') 立即注册
    section.show
      each val in posts
        article.col
          h3.author #{val.user}说
          p
            | #{val.post}
登入後複製

#首頁內容是繼承了範本檔案layout.jade.原書中使用的bootstrap來構建頁面的css佈局和樣式,這裡我自己手寫了一個仿bootstrap風格的佈局樣式,沒有應用bootstrap,style.css檔案如下:

body {
 padding: 50px;
 font: 14px "Lucida Grande", Helvetica, Arial, sans-serif;
}
html,body,ul,p,hr,h3{
  margin:0;
  padding: 0;
}
a {
 color: #00B7FF;
}
.header{
  background:#337aB7;
  width: 100%;
  height: 60px;
  color: #fff;
  font-size: 22px;
  overflow: hidden;
}
.list{
  line-height: 60px;
}
.navigation{
  overflow: hidden;
}
.list li{
  list-style: none;
  float: left;
  display: inline-block;
  margin-left: 20px;
  margin-right: 20px;
}
.list li a{
  text-decoration: none;
  color: #fff;
}

.list li a:hover{

}
.list li:not(:first-child) a:hover{
  font-size: 26px;
  color: #F5F5F5;
}
.logo{
  font-size: 26px;
  font-weight: 700;
}
.container{
  min-height: 500px;
  text-align: center;
  width: 100%;
}
.footer{
  width: 100%;
  height: 50px;
  font-size: 22px;
  background:#F5F5F5 ;
  line-height: 50px;
}
.footer a{
  color:#337aB7;
  text-decoration: none;
}
.main{
  color: #000000;
  width: 96%;
  margin: 30px auto;
}
.intro{
  width: 100%;
  margin:0 auto;
  border-radius: 5px;
  height: 300px;
  background:#F5F5F5 ;

}
.userintro{
  width: 100%;
  margin:0 auto;
  border-radius: 5px;
  height: 200px;
  background:#F5F5F5 ;
}
.welcome{
  padding-top: 50px;
  padding-left:50px;
  font-size: 50px;
  text-align: left;
  padding-bottom: 0;
  margin: 0;
}
.tech{
  text-align: left;
  padding-left:50px;
  margin: 0;
}
.show{
  overflow: hidden;
  width: 100%;
}
.show li{
  text-align: left;
  font-size: 18px;
}
.col{
  display: inline-block;
  float: left;
  width: 32%;
  height: 100px;
  overflow: hidden;
  padding-right: 20px;
  text-align: left;
  text-overflow: ellipsis;
}
.author{
  margin-top: 10px;
  margin-bottom: 3px;
}
.btnlist{
  padding-left: 50px;
  text-align: left;
}
.login{
  display: inline-block;
  padding-left: 15px;
  padding-right: 15px;
  height: 38px;
  line-height: 40px;
  background: -webkit-gradient(linear, left top, left bottom, from(#0068A6), to(#337aB7));
  color: #fff;
  text-align: center;
  border-radius: 5px;
  font-size: 20px;
  font-weight: 600;
  border: 1px solid #ccc;
  text-decoration: none;
  margin-right: 10px;
}
.register{
  display: inline-block;
  padding-left: 15px;
  padding-right: 15px;
  height: 38px;
  line-height: 40px;
  background: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#F5F5F5));
  color: #000;
  text-align: center;
  border-radius: 5px;
  font-size: 20px;
  font-weight: 600;
  border: 1px solid #ccc;
  text-decoration: none;
}
.field{
  margin-top: 20px;
  margin-left: 50px;
  text-align: left;
  margin-bottom: 20px;
  border:none;
  border-bottom: 1px solid #ccc;
}
.label{
  font-size: 18px;
  font-weight: 600;
  line-height: 100%;
  display: inline-block;
  width: 10%;
  vertical-align: middle;
  text-align: right;
  padding-right: 10px;
}
.regheader{
  text-align: left;
  font-size: 24px;
  font-weight: 600;
}
.regform{
  text-align: left;
  padding-left: 100px;
  margin-bottom: 20px;
}
.regform input[type='text'],input[type='password']{
  width: 200px;
  height: 20px;
}
.regform input[type='submit']{
  width: 120px;
  height: 30px;
  color: #fff;
  background:-webkit-gradient(linear, left top, left bottom, from(#0068A6), to(#337aB7));
  border-radius: 5px;
  font-size: 20px;
}

.item{
  margin:20px;
  width: 100%;
}
.mess{
  font-size: 18px;
  color: #E73C3C;
  background: #F2DEDE;
  border-radius: 5px;
  width: 300px;
  text-align: center;
  margin-left: 100px;
}
.indexmes{
  height: 30px;
  line-height: 30px;
  background: #F2DEDE;
  color: #E73C3C;
}
.article{
  width: 60%;
  height: 30px;
  border-radius: 3px;
  border: 1px solid #A3C732;
  margin-top: 5px;
  font-size: 20px;
}
.submit{
  height: 40px;
  vertical-align: middle;
  padding: 0;
  margin-top: -5px;
  margin-left: 5px;
  width: 80px;
  background: #A3c732;
  font-size: 20px;
  border: none;
  border-radius: 5px;
  color: #fff;
}
.submitform{
  margin-top: 25px;
  margin-left: -10px;
}
.userlink{
  display: inline-block;
  text-decoration: none;
  line-height: 38px;
  height: 38px;
  vertical-align: middle;
  padding: 0;
  margin-top: -8px;
  margin-left: 5px;
  width: 90px;
  text-align: center;
  background: #A3c732;
  font-size: 20px;
  font-weight: 600;
  border-radius: 5px;
  color: #fff;
  border: 1px solid #ccc;
}
.usertitle{
  text-align: left;
  padding-top: 5px;
  padding-bottom: 0;
  padding-left: 5px;
  margin-bottom: 8px;
}
.usersuccess{
  height: 30px;
  background: #DFF0D8;
  line-height: 30px;
  color: #3C7668;
}
登入後複製

#這個css檔案是專案中所有的css全部包含在這裡,所以比較龐大。到目前為止,可以查看首頁效果如下:

首页中的数据都是之前自己测试过程中加入的,这里主要为了查看首页效果,可以忽略这些数据。

由于这里要演示用户注册登录模块,用户注册模块的模板文件reg.jade如下:

extends layout
block content
  h3.field.regheader #{title}
  form.regform(method='post')
    p.mess #{message}
    p.item
      label.label(for='username') 用户名
      input(type='text',placeholder='输入注册用户名',id='username',name='username')
    p.item
      label.label(for='password') 用户密码
      input(type='password',placeholder='用户密码',id='password',name='password')
    p.item
      label.label(for='passwordconf') 重复密码
      input(type='password',placeholder='重复密码',id='passwordconf',name='passwordconf')
    p.item
      label.label
      input(type='submit' id='sub',name='sub' value='注册')
登入後複製

用户登陆模板login.jade如下:

extends layout
block content
  h3.field.regheader #{title}
  form.regform(method='post')
    p.mess #{message}
    p.item
      label.label(for='username') 用户名
      input(type='text',placeholder='输入登陆用户名',id='username',name='username')
    p.item
      label.label(for='password') 用户密码
      input(type='password',placeholder='用户密码',id='password',name='password')
    p.item
      label.label
      input(type='submit' id='sub',name='sub' value='登陆')
登入後複製

最终用户注册效果如下:

用户登录模块和这个效果相仿,就不查看了,少了一个重复密码的input而已。

下面我们需要编写用户注册的逻辑,在编写用户注册逻辑的前,用户数据需要持久化,所以首先要安装MongoDB数据库在自己的机器上.

MongoDB这种nosql类型的数据库,非常适合用户存储JSON对象类型的数据,有了mongoDB,就可以免去数据库表设计部分的工作,对比以前使用的mysql,sqlserver以及oracle还是非常方便的。关于mongoDB数据库的熟悉和学习,推荐其官网,官网详细介绍了该数据库的一切。英文不好可以去中文社区。同时为了使用nodejs来操作mongoDB数据库,我们使用mongoose这个对象模型,它是将mongoDB中的一个集合映射为nodejs中的一个model,然后在该model上提供操作这个集合的一些方法,使用它就可以避免我们自己利用nodejs提供的原生操作mongoDB数据库的语法去手写数据库CURD的方法,大大见晒了工作量,提高了开发效率。关于mongoose的学习,推荐去其官网,里面详述了它的安装,使用以及API调用情况。

解决了mongoDB安装和操作问题,我们来对数据库操作的model类,首先在项目路径下建立一个db.js文件,用来连接数据库并对数据库进行全局配置,如下

db.js

var settings=require("./settings");
var mongoose=require('mongoose');
mongoose.connect("mongodb://"+settings.ip+"/"+settings.db);
var db=mongoose.connection;
module.exports={
  "dbCon":db,
  "mongoose":mongoose
};
登入後複製

这里首先加载了配置文件settings.js文件,为了数据库便于灵活修改,我们将某些信息存储在配置文件中。然后加在了之前安装的mongoose模块,然后调用该模块的connect方法来连接我们配置的数据库,然后将连接以对象的形式返回供外部调用。

settings.js

module.exports={
  "ip":"localhost",
  "db":"microblog",
  "host":27071
};
登入後複製

MongoDB的默认端口是27071,一般可以使用默认端口即可,数据库连接大时候可以不指定端口,数据库名为microblog.

然后以db.js返回的数据库连接对象为基础,我们在项目根目录下创建一个models文件夹,用来存放数据模型。创建一个user.js映射我们数据库中的user集合(可以理解为user表),代码如下:

var mongoose=require('../db').mongoose;
var schema=new mongoose.Schema({
  name:'string',
  password:'string'
});
var User=mongoose.model('User',schema);
module.exports=User;
登入後複製

这里首先获得db.js中定义的连接对象,并以该对象为基础构造一个Schema(架构),mogoose操作数据库是以架构为基础的,类似于我们其他ORM模型中属性和方法的定义。这里我们定义了一个架构,拥有两个属性,name和password,都是string类型,对应用户的用户名和密码。然后利用该架构去创建一个model,该model上定义了对数据集合的增删改查等方法,不用我们自己再去定义和编写其他代码。在原书中这一节是利用node.js操作MongoDB数据库的原生API去定义了一个user对象,然后在user对象上自定义了一些CRUD的方法。可以看出,直接使用Mongoose可以大大减少开发量并且拥有更好的效率和性能。

到目前为止,我们已经有了界面(view),数据模型(model),就差逻辑代码(controller)没有编写了。在编写逻辑代码之前需要先说下express框架的特点以及它的整体运行方式。由于本人使用过一些类似的如Asp.net mvc,Yii以及thinkphp等MVC框架,使用express之后最大的感觉是这个框架够轻量级,尤其是express4.X之后,它仅仅保留了静态文件路径映射模块作为该框架本身的内置模块,其他的功能都以中间件的形式采用require(modulename)进行引入,只有引入后才能够使用该模块提供的功能。

express的工作原理是客户端发送一个request,express接到该请求,可以将它进行处理之后传递给其他中间件进行处理,最终处理完成之后,采用respond.end或者response.render进行页面渲染或响应,进行页面渲染的时候,采用参数传递页面需要的数据给对应模板引擎,模板引擎收到数据然后按照自己的语法进行替换生成对应的html,最终返回给浏览器进行渲染。

在express中,最关键的部分就是路有机制,我们所有基于请求做出的响应都是对该路由进行监听捕获的结果。举个例子,如果我们请求一个路径为http://localhost:3000/user,那么必须在routes文件夹下面的路径监听(暂且叫做监听吧)的js文件中编写对该请求的响应代码,诸如app.post('/user',function(...){...})之类的代码,如果不存在这样的代码,就会报一个404错误,因为请求没有得到响应,express实例不知道怎么去响应这个请求。以上就是express大致的原理和工作流程,对于它的学习,推荐去express官网直接去看文档,讲的很详细。

现在回到用户注册模块,我们注册用户常见的做法是注册成功之后就默认用户已经登录,直接跳转到欢迎登陆界面。在这里我们需要将用户数据在注册成功之后保存在session中,express框架对于session的支持是通过中间件express-session来的,使用方式依然是在npm 下安装,然后在项目主文件中使用require加载,最后调用其提供的API,为了使用session,必须先安装cookie的支持,这里利用cookie-parser这个中间件来为express框架提供cookie支持,它的具体使用方式可以去上面提供的地址自行查看。对于session,我们常见框架的做法是在服务器端将其存放到文件当中,由于这里我们有了MongoDB数据库,更理想的状态是将它存在数据库中,这样可以更灵活去控制。使用connect-mongo中间件可以将session存储到mongoDB中,具体使用方式可按地址查看。

上述概念明确之后,我们在项目根目录下的app.js(项目入口文件)中加载我们需要的中间件模块和自定义的模块如下:

app.js模块加载代码:

var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var routes = require('./routes/index');
var users = require('./routes/users');
var session = require("express-session");
var MongoStore=require('connect-mongo')(session);
var db = require('./db');
var app = express();

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');

// uncomment after placing your favicon in /public
//app.use(favicon(__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')));
app.use(session({
  secret:"myzhibie",
  store:new MongoStore({
  mongooseConnection:db.dbCon
  })
}));


 app.use('/', routes);
 app.use('/users', users);
登入後複製

上述代码就是加载各个中间件模块并采用app.use来load这个模块,其中上述代码的最后一指定了将session存储在MongoDB数据库中,secret属性是对session的签名,通常是一个字符串,这是必选项,如果不写,

是无法完成将session存储进入数据库的,关于该功能的更详细介绍请查看文档,最后两句app.use('/',routes)和app.use('/users',users)代表对于这两个路由的访问处理代码我们封装在了routes和users模块中,er这两个模块都在routes文件夹下面。

完成了模块引入加载和一些基本的设置,现在来编写用户注册的逻辑代码,上面说到对于路径/的访问处理在routes模块中,这个模块指的就是routes文件夹下面的index.js,部分代码如下:

var express = require('express');
var crypto = require('crypto');
var router = express.Router();
var db=require('../db');
var User=require('../models/user');
var Post=require('../models/post');
/* GET home page. */
router.get('/', function(req, res, next) {
  Post.find({},function(err,posts){
    if(err){
      req.session.message=err.message;
      return res.redirect('/');
    }
    res.render('index',{
      posts:posts
    });
  });

});
//发表微博
router.post('/post',function(req, res, next){
  var currentUser=req.session.user;
  var post=new Post({
    user:currentUser.name,
    post:req.body.article,
    updated:getTime(new Date())
  });
  post.save(function(err){
    if(err){
      req.session.message=err.message;
      return res.redirect('/reg');
    }
    req.session.success="发表成功";
    res.redirect('/users/'+currentUser.name);
  });


});

function getTime(date){
  return date.getFullYear()+
  "-"+date.getMonth()+1+"-"+
  date.getDate()+" "+
  date.getHours()+":"+
  date.getMinutes();
}
router.get('/reg', isLogin);
//用户进入注册页面
router.get('/reg',function(req,res){
  res.render('reg',{title:"用户注册"});
});
router.post('/reg', isLogin);
//用户点击注册按钮
router.post('/reg',function(req,res){
  if(req.body['password']!= req.body['passwordconf']){
    req.session.error="两次密码不一致";
    return res.redirect('/reg');
  }
  var md5=crypto.createHash('md5');
  var password=md5.update(req.body.password).digest('base64');
  var newUser=new User({
    name:req.body['username'],
    password:password
  });
  User.findOne({name:newUser.name},function(err,user){
    if(user){
      err="用户名已经存在";
    }
    if(err){
      req.session.error=err;
      return res.redirect('/reg');
    }
    newUser.save(function(err){
      if(err){
        req.session.error=err.message;
        return res.redirect('/reg');
      }
      req.session.user=newUser;
      req.session.success="注册成功";
      res.redirect('/');
    });
  });
});
router.get('/login',isLogin);
router.get('/login',function(req,res){
  res.render('login',{title:"用户登陆"});
});
router.post('/login',isLogin);
router.post('/login',function(req,res){
  var md5=crypto.createHash('md5');
  var password=md5.update(req.body.password).digest('base64');
  User.findOne({name:req.body.username},function(err,user){
    if(!user){
      req.session.error="用户不存在";
      return res.redirect('/login');
    }
    if(user.password!=password){
      req.session.error="密码错误";
      return res.redirect('/login');
    }
      req.session.user=user;
      req.session.success="登录成功";
      res.redirect('/');
  });
});
router.get('/logout',function(req,res){
  req.session.user=null;
  res.redirect('/');
});
function isLogin(req,res,next){
  if(req.session.user){
    req.session.message="用户已登录";
    return res.redirect('/');
  }
  next();
}
module.exports = router;
登入後複製

上述代码1-6行都是对外部模块的引入,8-19行是对首页路由/的处理代码。117行将该模块定义为router供外部调用。我们主要看54-83行,这些代码就是用户注册的代码,54行监听来自用户对于/reg路由的post请求,首先判断两次密码是否一致,如果不一致在session中存储一个错误信息然后跳转到到当前页面显示错误信息,该错误信息供模板引擎显示给用户。如果两次密码一致首先对密码进行md5加密,使用的是nodejs提供的核心模块crypto,并生成一个对象模型User,该对象模型是mongoose中提供的一个model的实例,mongoose在它上面定义了一些操作数据库的方法。然后调用这个实例的findOne方法检测该用户是否已经存在,如果存在就保存错误信息到session并跳转到当前页显示错误。如果不存在这样一个用户就使用save方法进行用户信息保存,注册成功后将用户信息保存在session中,并保存一个success的提示信息,然后跳转到首页。这里需要注意一个坑,以前做php或者.net的时候,我们通常都是先查询数据库等数据库返回结果提示用户是否存在之后再进行用户的save然后在跳转,这是一种同步方式,跳转操作需要等待findOne操作返回结果之后才能进行。而nodejs中采用异步IO,最后的跳转操作需要放在findOne操作的回调函数中进行,跳转操作不必等待findone操作结束后执行,两者是异步的。如果将最后的redirect操作放在findOne操作外部而不是回调函数中,你会在控制台上得到一个Can't set headers after they are sent的错误,这是因为在fineOne以及save操作之前已经进行行了跳转,response响应已经结束,不能够重复响应请求。

到目前为止,用户注册模块基本上已经差不多完成了,最后需要说一下如何在页面上显示提示信息或者错误信息,之前我们将提示信息或者错误信息都保存在了session中,jade要显示错误信息,它是不能够直接访问session的,在express2.X即原书中是利用req.flash API+动态视图助手来实现的,就是发生错误的时候先将其利用req.flash方法存储下来,然后利用动态视图助手结合模板去渲染给用户。express4.X废弃了这种方式,我们可以利用req.flash 的原理来自己模拟一个这种机制,同时利用res.locals变量被保存起来,模板在渲染的时候是能够访问到服务端这个变量的。关于res.locals的更多介绍请查看文档。

为了模拟这种req.flash机制,我们在项目入口文件app.js(项目根目录下)添加一段代码如下:

app.use(function(req,res,next){
//  res.locals.user=req.session.user;
  var err=req.session.error;
  var success=req.session.success;
  var user=req.session.user;
  var mess=req.session.message;
  delete req.session.success;
  delete req.session.error;
  delete req.session.message;
  if(err){
    res.locals.message="*"+err;
  }
  if(mess){
    res.locals.message="*"+mess;
  }
  if(success){
    res.locals.success=success;
  }
  if(user){
    res.locals.user=user.name;
  }
  next();
});
登入後複製

这段代码的意思是用户请求和响应的时候,捕获session中存储的错误信息和用户提示,将其存储在response.locals变量中,这样模板就能够获取。对于错误信息和提示,由于只使用一次,存储后立即使用delete删除,对于用户信息,需要持久保存下来,则不删除。

这样,就能够显示用户提示或者错误信息。

下面演示一下完整的用户注册流程以及错误信息提示。

当用户名存在或密码不一致时,

当注册成功后跳转到首页并显示用户注册成功

同时对于注册成功和登陆成功拥有不同提示,如果该用户已经是登录状态则显示退出和发表文章按钮,如果没有登录,则显示的是登陆和立即注册按钮。

以上就是利用nodejs及express,mongoose,mongoDB,jade进行web开发的主要流程,由于该项目是对nodejs web开发指南一书中微博项目的重构,所以完整版的项目代码还有用户权限控制(已登录用户不能够注册或登陆并提示),用户进入个人页面发布微博并列表显示,同时首页显示最近发布的微博信息等功能。完整版代码点这里,由于篇幅以及时间问题,上述要点不可能一一展开讨论,本文就作为一个提纲,是对nodejs web开发的一个综述。

以上就是本文的全部内容,希望对大家的学习有所帮助,更多相关内容请关注PHP中文网!

相关推荐:

关于NodeJS、NPM安装配置步骤(windows版本) 以及环境变量的介绍

基于webpack4搭建的react项目框架的方法

以上是如何快速使用node.js進行網頁開發的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

Python web開發框架比較:Django vs Flask vs FastAPI Python web開發框架比較:Django vs Flask vs FastAPI Sep 28, 2023 am 09:18 AM

Pythonweb開發框架比較:DjangovsFlaskvsFastAPI引言:在Python這個廣受歡迎的程式語言中,有許多出色的web開發框架可供選擇。本文將聚焦在三個流行的Pythonweb框架:Django、Flask和FastAPI。透過比較他們的特點、使用場景和程式碼範例,幫助讀者更好地選擇適合自己專案需求的框架。一、Django作

Pi Node教學:什麼是Pi節點?如何安裝和設定Pi Node? Pi Node教學:什麼是Pi節點?如何安裝和設定Pi Node? Mar 05, 2025 pm 05:57 PM

PiNetwork節點詳解及安裝指南本文將詳細介紹PiNetwork生態系統中的關鍵角色——Pi節點,並提供安裝和配置的完整步驟。 Pi節點在PiNetwork區塊鏈測試網推出後,成為眾多先鋒積極參與測試的重要環節,為即將到來的主網發布做準備。如果您還不了解PiNetwork,請參考Pi幣是什麼?上市價格多少? Pi用途、挖礦及安全性分析。什麼是PiNetwork? PiNetwork項目始於2019年,擁有其專屬加密貨幣Pi幣。該項目旨在創建一個人人可參與

使用Angular和Node進行基於令牌的身份驗證 使用Angular和Node進行基於令牌的身份驗證 Sep 01, 2023 pm 02:01 PM

身份驗證是任何網路應用程式中最重要的部分之一。本教程討論基於令牌的身份驗證系統以及它們與傳統登入系統的差異。在本教程結束時,您將看到一個用Angular和Node.js編寫的完整工作演示。傳統身份驗證系統在繼續基於令牌的身份驗證系統之前,讓我們先來看看傳統的身份驗證系統。使用者在登入表單中提供使用者名稱和密碼,然後點擊登入。發出請求後,透過查詢資料庫在後端驗證使用者。如果請求有效,則使用從資料庫中獲取的使用者資訊建立會話,然後在回應頭中傳回會話訊息,以便將會話ID儲存在瀏覽器中。提供用於存取應用程式中受

重新構思架構:將WordPress用於網頁應用程式開發 重新構思架構:將WordPress用於網頁應用程式開發 Sep 01, 2023 pm 08:25 PM

在本系列中,我們將討論如何使用WordPress建立Web應用程式。儘管這不是我們將研究程式碼的技術系列,但我們涵蓋了框架、基礎、設計模式、架構等主題。如果您還沒有閱讀該系列的第一篇文章,我推薦您閱讀;但是,出於本文的目的,我們可以將上一篇文章總結如下:簡而言之,軟體可以建立在框架上,軟體可以擴展基礎。簡單地說,我們區分了框架和基礎——這兩個術語在軟體中經常互換使用,儘管它們不是同一件事。 WordPress是一個基礎,因為它本身就是一個應用程式。它不是一個框架。為此,當涉及到在WordPres

C++與其他Web開發語言相比有哪些優點和缺點? C++與其他Web開發語言相比有哪些優點和缺點? Jun 03, 2024 pm 12:11 PM

C++在網路開發中的優勢包括速度、效能和低階訪問,而限制包括學習曲線陡峭和記憶體管理要求。在選擇Web開發語言時,開發人員應根據應用程式需求考慮C++的優點和限制。

如何開始使用C++進行Web開發? 如何開始使用C++進行Web開發? Jun 02, 2024 am 11:11 AM

要使用C++進行Web開發,需要使用支援C++Web應用程式開發的框架,如Boost.ASIO、Beast和cpp-netlib。開發環境中,需要安裝C++編譯器、文字編輯器或IDE以及Web框架。建立Web伺服器,例如使用Boost.ASIO建立伺服器。處理用戶請求,包括解析HTTP請求、產生回應並將其發送回客戶端。可以使用Beast函式庫解析HTTP請求。最後,可以開發一個簡單的Web應用程序,例如使用cpp-netlib庫建立RESTAPI,實現處理HTTPGET和POST請求的端點,並使用J

Golang常見的應用場景在軟體開發有哪些? Golang常見的應用場景在軟體開發有哪些? Dec 28, 2023 am 08:39 AM

Golang作為一種開發語言,具有簡潔高效、並發效能強等特點,因而在軟體開發上有著廣泛的應用場景。以下將介紹一些常見的應用場景。網路程式設計Golang在網路程式設計方面表現出色,特別適合打造高並發、高效能的伺服器。它提供了豐富的網路庫,開發人員可以方便地進行TCP、HTTP、WebSocket等協定的程式設計。 Golang的Goroutine機制讓開發者可以輕鬆地編

學習C++ Web開發所需的技能和資源有哪些? 學習C++ Web開發所需的技能和資源有哪些? Jun 01, 2024 pm 05:57 PM

C++Web開發需掌握C++程式設計基礎、網路協定與資料庫知識。必備資源包含cppcms、Pistache等Web框架,cppdb、pqxx等資料庫連接器,以及CMake、g++、Wireshark等輔助工具。透過學習實戰案例,如創建簡單的HTTP伺服器,可以開啟C++Web開發之旅。

See all articles