express介绍

1,561 阅读6分钟

express的介绍

express官网:www.expressjs.com.cn/

Express是一个基于node.js的极简、灵活的web应用开发框架。

Express可以快速搭建一个完整功能的网站。

Express的作用于node.js中的内置的http模块类似,都是用来创建web服务的。但是http模块使用起来比较繁琐。开发效率低,Express是基于http模块封装出来的,能够极大的提高开发效率。

http与Express的关系:JavaScript原生操作DOM 与 JQuery的关系。

安装Express

在项目的根目录下,输入【npm init】初始化。

运行

npm i express

创建服务器

const express = require("express")
//创建服务
let app = express();
​
app.get("/",(req,res)=>{
  res.send("Hello,world!")
})
​
app.listen(3000,()=>{console.log("服务器已启动");})

路由

什么是路由

路由就是网址,web服务器会根据用户输入的不同路径和请求方式,响应不同的页面。

基本格式

路由的组成:请求地址+请求方式。

http常见的请求方式:post(添加),get(获取)put(更新)delete(删除)

app.method(path,handler)
//method:请求方式
//path:请求路径
//handler:请求的处理函数。

匹配规则:每当一个请求到达服务器后,需要经过路由的匹配。匹配请求地址和请求方式,匹配成功后,才会调用对应的处理函数。

模块化路由

为了方便对路由进行管理,Express不建议我们将所有的路由都罗列在一个文件中。

我们可以将路由分类,将同一类的路由抽离为一个模块。

  1. 创建路由模块对应的js文件
  2. 调用express.Rotuer()方法创建路由对象。
  3. 在路由对象上挂载具体的路由。
  4. 使用module.exprots导出路由对象
  5. 在app.js中使用app.use方法来注册路由模块。

order.js文件如下

const express = require("express");
/**
 * 订单路由模块
 */
// 2.调用express.Rotuer()方法创建路由对象。
const order = express.Router();
​
//3.在路由对象上挂载具体的路由。
order.post("/order/add",(req,res)=> res.send("新增了一个订单"));
order.post("/order/edit",(req,res)=> res.send("修改了订单信息"));
order.post("/order/del",(req,res)=> res.send("删除了一个订单"));
order.get("/order/list",(req,res)=> res.send("查询所有的订单信息"));
​
//4.使用module.exprots导出路由对象
module.exports = order;

app.js文件如下

//引入express框架
const express = require('express');
//创建网站服务器
const app = express();
const order = require('./order');
app.use(order);
//app.use('/home',home); 
app.listen(3000, function () {
  console.log('Example app listening on port 3000!')
})

获取get参数

Express框架中使用req.query即可获取GET参数,框架内部会将GET参数转换为对象并返回。

app.get("/login",function(req,res){
    console.log(req.query);
    res.send("登录");
});

获取post参数

// 如果设置为false,那么对URL-encoded的数据的解析采用querystring
// 默认值为true,但是不赞成使用默认值。
 app.use(express.urlencoded({ extended: false }));
 // 接收请求
 app.post('/add', (req, res) => {
    // 接收请求参数
    console.log(req.body);
 }) 

动态参数

通过req.params对象,可以访问到url中,通过:匹配到的动态参数。

const express = require("express");
var app = express();
 
app.get("/",function(req,res){
    res.send(`<h1>oh no</h1>`);
});
app.get("/login/:aid",function(req,res){
    res.send(req.params);
});
app.listen(3000);

中间件

中间件介绍

中间件就是处理HTTP请求的函数,做接收到请求和发送响应中间的一系列操作。

注册中间件

通过使用app.use()app.METHOD()注册中间件,其中METHOD是请求方法的小写(如GET、PUT或POST)

app.use 匹配所有的请求方式,接收所有的请求。

 app.use((req, res, next) => {
     console.log(req.url);
     //注意:在当前中间件处理完毕后,必须调用next()函数
     //表示调用下一个中间件或路由。
     next();
 });

中间件的作用

多个中间件之间,共享同一份req和res,基于这样的特性,我们可以在上游的中间件中,为req或res对象添加自定义的属性或方法,供下游中间件或路由使用。

案例:获取请求到达服务器的时间。

如果按照之前的写法,我们需要在每个路由函数中进行处理。

 app.use((req, res, next) => {
     console.log(new Date());
     next();
 });

案例:请求不到的路由,响应404

app.get('/login',(req,res)=>{
    res.render('login',{login:'123'})
})
app.post('/dologin',(req,res)=>{
    res.send(req.body);
})
// 错误处理中间件  //类似于拦截器
app.use((req,res)=>{
    res.status(404).send('不存在');
});

定义多个全局中间件

可以使用app.use()连续定义多个全局中间件,客户端请求到达服务器之后,会按照中间件定义的先后顺序依次进行调用

注意事项

  1. 一定要在路由之前注册中间件。
  2. 客户端发送来的请求,可以连续调用多个中间件进行处理。
  3. 执行完中间件的代码之后,不要忘记调用next()函数。
  4. 为了防止代码逻辑混乱,调用next()函数后不要再写额外的代码。

案例:错误处理中间件

顾名思义,它是指当程序出现错误时所执行的操作。比如,匹配不到路由,文件读取失败等等。错误处理中间件和其他中间件基本一样,只不过其需要开发者提供4个自变量参数。

错误中间件放到最后,才可以接受到错误。通过接受err参数判断是否触发该中间件

const express = require('express')
const fs = require('fs')
const path = require('path')
const app = express()

app.get('/a',(req, res, next) => {
    res.end('hello')
})


app.get('/',(req, res, next) => {
    try {
        const data = JSON.parse("{name:}");
        res.send(data);
    }catch (e){
        next(e);
    }
})

/*
app.get('/',(req, res, next) => {
    fs.readFile(path.join(__dirname,"ccc.log"),(err,data)=>{
        if(err){
            next(err);
        }
    });
})
*/

/*
    统一的错误处理日志中间件
 */
app.use((err,req, res, next) => {
    const err_log = `
        +---------------+-------------------------+
        错误名称:${err.name},\n
        错误信息:${err.message},\n
        错误时间:${new Date()},\n
        错误堆栈:${err.stack},\n
        +---------------+-------------------------+
    `
    fs.appendFile(path.join(__dirname,"error.log"),err_log,()=>{
        res.writeHead(500,{'Content-Type':'text/html;charset=utf-8'});
        res.end(`500 服务器内部错误`);
    });
})

app.listen(3000,()=>{
    console.log('running```')
})

静态资源访问

const express = require('express')
const path = require('path')
const app = express()
// path.join(__dirname, 'public') 表示工程路径后面追加 public
app.use(express.static(path.join(__dirname, 'public')))

app.listen(3000, () => {
  console.log(`App listening at port 8080`)
})

【注意】Express在指定的静态目录中查找文件,并对外提供资源的访问路径。因此,存放文件的目录名不会出现在URL中。

多个静态资源目录

如果要托管多个静态资源目录,多次调用express.static方法即可,但是需要注意的一点是:express会根据目录的添加顺序查找所需的文件。

ejs模板引擎

模板引擎是什么

模版引擎能帮我们我们动态的生成 HTML 内容。且可以实现HTML代码与js代码的分离。

使用方法

下载安装

cnpm install ejs --save

设置

//设置默认使用的模板引擎
app.set("view engine", "ejs");

app.get("/", (req,res)=>{
    res.render("index"); //不需要写res.render("./views/index.ejs");
})

新建ejs文件

新建views文件夹存放模板文件。在views文件夹下新建ejs文件,注意,扩展名必须是ejs,不是html。

渲染数据

app.get("/",(req,res)=>{
        //呈递页面
        res.render("index",{
            "name" : "zhangsan" 
        }); 
});

ejs 的语法

插值语句 <%= value %>

<p><%= title %></p>

流程控制语句 if语句 <% js代码 %>

  1. if语句
//  js 的if 语句格式
<% if(条件) { %>
//  处理的逻辑 渲染的HTML结构
<% } %>
  1. if-else语句
//  js 的if 语句格式
<% if(条件) { %>
//  处理的逻辑 渲染的HTML结构
<% }else { %>
//  处理的逻辑 渲染的HTML结构
<% } %>
  1. if-else的嵌套
//  js 的if 语句格式
<% if(条件) { %>
//  处理的逻辑 渲染的HTML结构
<% }else  if(){ %>
//  处理的逻辑 渲染的HTML结构
<% }else if(){ %>
// .....
<% else {%>
// ...
<% }%>

流程控制语句 for循环语句 <% js代码 %>

  1. for循环
<%for(let i = 0; i < arr.length; i++) {%>
//  处理的逻辑 渲染的HTML结构
<% } %>
  1. forEach 循环
<% arr.forEach(function(item, index) { %>
//  处理的逻辑 渲染的HTML结构
<% }) %>