Node.js Express框架

一、Express 介绍

       Express是一个最小的,灵活的Node.js Web应用程序框架,它提供了一套强大的功能来开发Web和移动应用程序。 它有助于基于Node Web应用程序的快速开发。Express框架的核心功能是:

  • 允许设立中间件响应HTTP请求
  • 定义了用于执行基于HTTP方法和URL不同动作的路由表
  • 允许动态渲染基于参数传递给模板HTML页面

二、安装Express

        安装Express 框架全局使用NPM,以便它可以被用来使用Node终端创建Web应用程序。

               $ npm install -g express-generator

       上面的命令在本地node_modules目录保存安装,并创建一个目录express在node_modules里边。还有,应该使用express安装以下几个重要的模块:

  1. body-parser :这是一个Node.js中间件处理JSON,Raw,文本和URL编码的表单数据
  2. multer :这是一个Node.js的中间件处理multipart/form-data
  3. cookie-parser : 解析Cookie头和填充req.cookies通过cookie名字键控对象

               $ npm install body-parser --save

               $ npm install cookie-parser --save

               $ npm install multer --save

三、Express创建项目

       一个非常基本的Express应用程序,它会启动服务器,并侦听端口3000等待连接。这个应用程序使用"Hello World! "回应!为请求网页。 对于所有其他路径,这将响应一个404表示未找到。

       1、进入工作目录(自定义)

       2、执行创建命令,创建一个名为hello的Express项目

              express hello

       表示安装成功

       3、进入hello目录安装依赖包:

             F:\hello> npm  install

       4、安装完成后,执行命令启动应用:

             F:\hello>npm  start

       5、在浏览器中输入http://localhost:3000/

 四、Express项目结构分析

           1、bin:启动配置文件,在www 里修改运行端口号
           2、node_modules:存放所有的项目依赖库,就像java存放架包
           3、public:用于存放静态资源文件 图片,CSS,JAVASCRIPT文件..
           4、routers:路由文件相当于springmvc中的Controller,ssh中的action
           5、views:存放页面的地方
           6、package.json:项目依赖配置及开发者信息。
           7、app.js:应用核心配置文件,项目入口

五、app.js配置详解

       app.js文件相当于项目启动的主入口文件,包含以下公共方法和服务器配置信息等

var createError = require('http-errors');//http错误处理模块
var express = require('express');//引入Express
var path = require('path');//引入path
var cookieParser = require('cookie-parser');//引入cookie处理对象
var logger = require('morgan');//引入日志模块

//引入路由目录中的index.js文件
var indexRouter = require('./routes/index');
//引入路由目录中的users.js文件
var usersRouter = require('./routes/users');
var app = express(); //创建express应用
// view engine setup
app.set('views', path.join(__dirname, 'views')); //定义页面目录
app.set('view engine', 'jade');//定义页面模板引擎
app.use(logger('dev'));//定义日志打印级别
app.use(express.json());//定义json格式处理数据
//定义使用urlencode处理数据及querystring模块解析数据
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());//定义使用cookie处理对象
app.use(express.static(path.join(__dirname, 'public')));//定义静态资源目录public
app.use('/', indexRouter);//定义指向index.js的路由
app.use('/users', usersRouter);//定义指向users.js的路由
// 定义404错误处理
app.use(function(req, res, next) {
  next(createError(404));
});
// 定义其他错误处理
app.use(function(err, req, res, next) {
  // 设置 locals, 只在开发环境生效
  res.locals.message = err.message;
  res.locals.error = req.app.get('env') === 'development' ? err : {};
  // 返回错误http状态码
  res.status(err.status || 500);
  res.render('error');//渲染错误页面
});
module.exports = app; //导出app

一个页面的运行过程和逻辑大致分为三步,路由中间件(index.js)的书写同时中间件的模板(index.ejs)要写好、最后由app.js配置和调用路由中间件。

      1、app.js配置

      2、routes 调用路由级中间件

      3、views 模板渲染

六、Express路由:

       路由用于确定应用程序如何响应对特定端点的客户机请求,包含一个 URI(或路径)和一个特定的 HTTP 请求方法(GET、POST 等)。

    每个路由可以具有一个或多个处理程序函数,这些函数在路由匹配时执行。它的使用形式如下:

app.method(path, handler)

          app:是 express 的实例。
    method:是 HTTP 请求方法。
         path:是服务器上的路径。
    handler:是在路由匹配时执行的函数。

注意如果有多个路由处理程序,那么不是最后一个路由的情况下,其参数要有next:

       next() 函数不是 Node.js 或 Express API 的一部分,而是传递给中间件函数的第三自变量。next() 函数可以命名为任何名称,但是按约定,始终命名为“next”。为了避免混淆,请始终使用此约定。

       next函数主要负责将控制权交给下一个中间件,如果当前中间件没有终结请求,并且next没有被调用,那么请求将被挂起,后边定义的中间件将得不到被执行的机会。

七、Express的页面

      1、更换模板引擎

          Express默认的模板引擎是jade,为了方便用户开发,可以把它替换成更简洁、更高效的art-template

         (1)安装art-template依赖包

              npm  install  -S  art-template

              npm  install  -S   express-art-template

        (2)修改app.js文件

              app.engine(‘.html’,requare(‘express-art-template’)

              app.set(‘view engine’,’html’)

2、渲染数据到页面

       在开发网页的时候,网页上的内容往往不是一成不变的,而是根据服务端内容变换的,这就需要将数据渲染到页面上。即调用response的render方法向页面传递数据,在页面中使用{{ 变量名 }}接收服务端的数据

router.get('/post',function(req,res){
  res.render('post',{
    title:'孔子学院',
    name:'张三',
    age:31,
   happy:true
  })
})

 前端页面:

     <p>
         姓名:{{name}}
         <br><br>
         年龄:{{age}}
     </p>

        (1)条件渲染:根据不同的情况展示不同的页面

<h2>{{title}}</h2>
   <!-- 判断年龄小于30-->
   {{ if age<30 }}
       <p>大家好,我是{{name}},我今年{{age}}岁,很高兴认识大家!</p>
   {{ /if }}
   <!-- 判断年龄大于等于30 -->
   {{ if age>30 }}
       <p>大家好,我是{{name}},很高兴认识大家!</p>
   {{ /if }}

         (2)嵌套条件渲染

   <h2>{{title}}</h2>
   <!-- 判断年龄小于30-->
   {{ if age<30 }}
      <p>大家好,我是{{name}},我今年{{age}}岁,很高兴认识大家!</p>
   {{ /if }}

   <!-- 判断年龄大于等于30 -->
   {{ if age>30 }}
      <p>大家好,我是{{name}}
          <!-- 判断happy字段是否为真-->
          {{ if happy }}
            <span>很高兴认识大家!</span>
          {{ /if }}
      </p>
   {{ /if }}

         (3)循环渲染:

router.get('/post',function(req,res){
  res.render('post',{
    title:'德云IT学院',
    list:[{
      id:1,
      content:'今天天气不错'
    },{
      id:2,
      content:'昨天几点睡觉的?'
    },{
      id:3,
      content:'工作好累'
}],
  });
});

页面:

   <h2>{{title}}</h2>
   {{ each list as item}}
      <p>id:{{item.id}},内容:{{item.content}}</p>
   {{ /each }}

         (4)循环渲染结合条件渲染:

router.get('/post',function(req,res){
  res.render('post',{
    title:'德云IT学院',
    list:[{
      id:1,
      content:'今天天气不错'
    },{
      id:2,
      content:'昨天几点睡觉的?'
    },{
      id:3,
      content:'工作好累'
    }],
    targetId:2
  });
});

页面:

   <h2>{{title}}</h2>
   {{ each list as item}}
     {{ if item.id === targetId}}
       <p style="color:#f00">id:{{item.id}},内容:{{item.content}}</p>
     {{ else }}
       <p>id:{{item.id}},内容:{{item.content}}</p>
     {{ /if }}
   {{ /each }}

三、请求对象Request

       req.params一个数组,包含命过名的路由参数

<a href="http://localhost:8089/test/12/15">params</a>

后台:

router.get('/post/:id/:userid',function(req,res){
  res.send(req.params)
});

     req.queryget请求的查询字符串参数

     req.bodypost的请求体内容

     req.cookies一个对象,包含从客户端传递来的cookie信息

     req.headers一个对象,从客户端接到的请求抱头

     req.path请求路径,不包含协议,端口,查询字符串

     req.host主机名

     req.xhrboolean值,判断请求是否是ajax请求

     req.protocol用于标示协议http,https

     req.urlpath+查询字符串

四、响应对象Response

       res.status(code)设置http状态码,express默认是200。可利用此函数返回404或者500页面,重定向的话用redirect()

       res.send(options):向客户端发送响应数据,可以是一个对象(key-value)

       res.render(视图名,数据):页面的文件名(不带扩展名),“数据”是向页面发送的数据

       res.cookie(name,value,[options])设置cookie值

       res.clearCookie(name,[options])清除cookie值

       res.redirect([status],url)重定向浏览器,默认状态:302

       url是路由里面的路径而不是视图里面的路径

       res.json([status],json)向客户端发送json数据及其可选的状态

       res.jsonp([status],jsonp)

       res.send([status],body)向客户端发送响应及其状态吗

       res.type(type)相当于res.set(‘Content-Type‘,‘type‘)

五、get请求:

一般在网站开发中,get都用作数据获取和查询,类似于数据库中的查询操作,当服务器解析前台资源后即传输相应内容;而查询字符串是在URL上进行的,形如:
           http://localhost:8080/login?goods1=0001&goods2=0002

  (1)GET 请求的特点:

  • GET 请求可被缓存
  • GET 请求保留在浏览器历史记录中
  • GET 请求可被收藏为书签
  • GET 请求不应在处理敏感数据时使用
  • GET 请求有长度限制

          IE:对URL的最大限制为2083个字符,若超出这个数字,提交按钮没有任何反应。

         Firefox:对Firefox浏览器URL的长度限制为:65536个字符。

          Safari:URL最大长度限制为80000个字符。

         Opera:URL最大长度限制为190000个字符。

          Google(chrome):URL最大长度限制为8182个字符。

  • GET 请求只应当用于取回数据

   (2)示例

        在views下创建login.html文件

<form action="http://localhost:8082/login" method="get">
    用户:
    <input type="text" name="user" id="user" placeholder="用户名"/>
    <br>
    密码:
    <input type="password" name="password" id="password" placeholder="密码"/>
    <br>
    <input type="submit" value="提交"/>
</form>

        更改router下的index.js文件(路由文件)

var express = require('express');
var router = express.Router();

/* GET login page. */
router.get('/', function(req, res, next) {
  res.render('login');
});
/* 获取登录页面的参数 */
router.get('/login',function(req,res){
  console.log(req.query);
  res.send("登录路由,user为:"+req.query.user+"==>   password为:"+req.query.password)
})
module.exports = router;

六、post请求:

      示例:

       在views下创建post.html文件

<form action = "http://localhost:8082/add" method="POST">
        用户:<input type="text" name = "userName"> 
        <br><br>
        密码:<input type="password" name = "userPwd"> 
        <br><br>
        <button type="submit">提交</button>
</form>

      配置router下的index.js文件(路由文件)

//获取post页面
router.get('/post',function(req,res,next){
  res.render('post')
})
//获取post方式的请求参数
router.post('/add',(req,res)=>{
  res.send("登录路由,user为:"+req.body.userName+"==> password为:"+req.body.userPwd)
})

附:每次更改路由文件都要重新启动项目才能生效,这样开发效率不高。可以安装nodemon工具,在更改路由后就不用重新启动项目了

1、安装nodemon工具

       npm  install  -g  nodemon

2、修改项目根目录中的package.json文件

"scripts": {
    "start": "node ./bin/www"
  }

改为:

"scripts": {
    "start": "nodemon ./bin/www"
  }