node的express模块

总结

初始化

  • 一、创建一个空的目录、项目包初始化(npm init -y / yarn init -y)
    下载express包:npm i express / yarn add express
    这个包下载的时候一定是一个生产环境依赖

创建一个服务文件(server.js)

  • 二、创建一个服务文件(server.js)

    • 2.1 导包(引入模块)
      const express = require('express');

    • 2.2 创建服务对象
      const app = express();

    • 2.3 建立路由规则

      app.get('/路由名称',(request,response)=>{}) get请求

      app.post('/路由名称',(request,response)=>{}) post请求

      app.put('/路由名称',(request,response)=>{}) put 修改请求

      app.patch('/路由名称',(request,response)=>{}) patch修改请求

      app.delete('/路由名称',(request,response)=>{}) delete 删除请求

      app.all('/路由名称',(request,response)=>{}) all代表所有的请求方式 都能进入此路径

      app.all('*',(request,response)=>{}) – 这条路由规则放在最后
      *表示所有的路径的匹配(全局路径的通配符)
      注意事项:*表示的所有路径,包含前面所规定的固定的名称的路径,如果放在最前面那么用户输入什么路由规则都满足,那么我们一般放在路由规则的最后

    • 2.4 建立监听端口

      app.listen(端口号,()=>{
      console.log(‘xx端口号正常运行中…’)
      })

请求报文对象 request

  • 三、请求报文对象 request

  • 请求行:
    请求类型:request.method
    请求url: request.url
    http协议版本:request.httpVersion

    • 请求头:request.headers 返回的一个对象

      let {host,connection} = request.headers;

      get虽然没有请求体传递数据,但是可以通过请求字符串的方式传递

    • 请求字符串:?参数名=参数值&参数名=参数值…

      请求字符串的出现情况:

      • 1)可以直接在url地址的后面手动输入:http://localhost/user?a=1&b=2
      • 2) 表单get提交方式:需要给要提交的表单元素添加一个name属性 name属性名就是query对象键名 属性值就是用户填写值
      • 3)超链接< a href=“http://localhost/路由名称?参数名=参数值&参数名=参数值”>xxx< /a >

    获取请求字符串request.query 返回的也是一个对象 {a:1,b:2}

    路由占位符:出现一定是url中的某一些位置的值是不确定的,则这个不确定的位置就可以使用占位符来规定
    占位符就是一个单词的符号,可以自定义
    http://www.jd.com/10-149.html
    http://www.jd.com/10-120.html

    例如:http://www.jd.com/10-:id/20-:id1.html
         http://www.jd.com/10-100/20-200.html

获取占位符中的内容:request.params 返回的也是一个对象 {id:100,id1:200}

响应报文对象 response

  1. 四、响应报文对象 response
  • 响应行:
    response.statusCode = 状态码;
    response.statusMessage = 值;
    response.status(状态码)

  • 响应头:
    response.setHeader('头名','头值');

    例如:

    response.setHeader('Content-Type','text/html;charset=utf-8');
    response.setHeader('Access-Control-Allow-Origin','*'); 设置跨域

    Content-Type的设置
    ('Content-Type', 'application/x-www-form-urlencoded') 设置post请求的数据格式
    ('Content-Type', 'text/html;charset=utf-8') 数据可以是纯文本也可以是html 类似于innerHTML
    ('Content-Type', 'text/plain;charset=UTF-8') 数据是纯文本格式 类似于innerText
    ('Content-Type', 'application/json; charset=utf-8') JSON格式的数据

  • 响应体:

    response.end()

    以下方法是express扩展的
    response.send("xxxx");返回字符串
    response.json({name:"姓名"});返回对象

    end和send的区别
    send是setHeader方法+end方法的姐合,将响应头的响应体的数据类型以及字符集和end方法结合
    response.setHeader(‘Content-Type’,‘text/html;charset=utf-8’);

    response.download(__dirname+'/文件路径') 响应下载文件
    response.sendFile(__dirname+'/文件路径') 将文件的内容进行输出

    [redirect后期项目会用到] 路由的重定向
    response.redirect('/路由名称') 直接定向到某一个路由规则
    response.redirect('/路由名称?参数名=参值...') 定向到某一个路由规则并且传递请求字符串参数
    response.redirect('外网网址') 定向到外网网址

    注意事项:download、sendFile、redirect都可以直接使用,不和end连用,
    否则不使用这几种方式那么必须代码的最后要设置响应体(end/send)

// 1引入express模块
const express = require('express');
// 2创建服务对象
const app = express();
// 3设置路由规则

// get 请求
app.get('/login',(request,response)=>{//request 请求报文对象  response响应报文对象
  // 请求报文 行 头 空行 体
  const {method , url , httpVersion, headers:{host , connection}} = request;
  // method 请求类型  url 请求地址 headers 请求头 host 主机  httpVersion 版本号

  //获取请求字符串 http://localhost/user?a=1&b=2 
  request.query //{a:1,b:2}

  // end和send的区别
  //send是setHeader方法+end方法的姐合,将响应头的响应体的数据类型以及字符集和end方法结合
  //response.setHeader('Content-Type','text/html;charset=utf-8');
  response.send('登录成功');
}) 

// post请求 
app.post('/register/:id/:age',(request,response)=>{
   //获取路由占位符中的内容 http://localhost/register/15/18?a=1&b=2 
  request.params ;//{id:15,age:18}
  response.send('注册成功');
})

// all代表所有的请求方式 都能进入此路径
app.all('/user',(request,response)=>{
  // 响应状态码
  response.statusCode;
  // 响应状态字符串
  response.statusMessage;
  // 设置响应头
  response.setHeader('aa','11');//自定义响应头
  // 响应下载文件
  response.download(__dirname+'index.txt');
  // 将文件的内容进行输出
  response.sendFile(__dirname+'index.txt');

  // 路由的重定向
  //直接定向到某一个路由规则
  response.redirect('./uesr')
  //定向到某一个路由规则并且传递请求字符串参数
  response.redirect('/denglu?name=admin&age=23&pass=123');
  //定向到外网网址
  //注意事项:外网网址一定要写协议!!!
  response.redirect('http://www.baidu.com');

  // 设置响应状态码
  response.status(400)

   //注意事项:download、sendFile、redirect都可以直接使用,不和end连用,
  //否则不使用这几种方式那么必须代码的最后要设置响应体(end/send)
})

//*表示所有的路径的匹配(全局路径的通配符)
//注意事项:*表示的所有路径,包含前面所规定的固定的名称的路径,如果放在最前面那么用户输入什么路由规则都满足,那么我们一般放在路由规则的最后
app.post("*",(request,response)=>{
  response.end('404 not Found');
})

//4设置监听端口
app.listen(8080,()=>{
  console.log('8080端口服务启动成功');
})

中间件

  1. 五、中间件
  • 全局中间件
    • 定义单个全局中间件
let recordMiddleware = function(request,response,next){
//实现功能代码
//.....
//执行 next 函数(当如果希望执行完中间件函数之后,仍然继续执行路由中的回调函数,必须调用 next)
next();
}

app.use(recordMiddleware);

简写形式

app.use(function(request,response,next){
next();
});
    • 定义多个全局中间
方式一
app.use(function (request, response, next) {
console.log('定义第一个中间件');
next();
})
app.use(function (request, response, next) {
console.log('定义第二个中间件');
next();
})
方式二
//或者
/*let loginMiddleWare = (request, response, next) => {
console.log('我是全局中间件 1');
next();
}

let login1MiddleWare = (request, response, next) => {
console.log('我是全局中间件 2');
next();
}

app.use(login1MiddleWare, loginMiddleWare);*/
  • 路由中间件

    • 定义单个路由中间件
      app.get('/路由规则',中间件函数,(request,response)=>{});
定义中间件函数 m1
const m1 = function(request,response,next){
  console.log('这是中间件函数');
}
创建路由规则
app.get('/',m1,(request,response)=>{
  response.end('Home Page');
});
    • 定义多个路由中间件
 方式一
app.get('/路由规则',`中间件函数1`,`中间件函数2`,(request,response)=>{});
或者方式二
app.get('/路由规则',[中间件函数1,中间件函数2..],(request,response)=>{});
  • 静态资源中间件的使用
    app.use(express.static('./public'));
    app.use('/upload',express.static(path.join(__dirname,'./upload')))代表的意思是在/upload路由中访问项目中./upload文件夹下的静态资源文件,前端通过访问/upload + 文件名来获取文件
    在这里插入图片描述

获取 post 请求的请求体数据 body-parser

  1. 六、获取 post 请求的请求体数据 body-parser
    1、安装
 npm i body-parser

2、导入 body-parser 包

const bodyParser = require('body-parser');

3、设置使用 body-parser 中间件

//extended:true,那么你可以解析嵌套对象,或者通常是任何类型
//extended:false,则只能解析字符串或数组
app.use(bodyParser.urlencoded({extended:false}));

4、使用 request.body 来获取请求体数据

app.post('/login',(request,response)=>{
	//获取请求体数据
	//console.log(request.body);
	//用户名
	console.log(request.body.username); //admin
	//密码
	console.log(request.body.userpass); //123456
response.send('获取请求体数据');
});

Router 路由器

  1. 七、Router 路由器

子文件

//1、导入包
const express = require('express');
//2、创建子路由对象
const userRoutes = express.Router();
//3、通过子路由对象来规定路由规则
userRoutes.get('/user', (request, response) => {
response.send('用户功能');
})
//4、暴露模块
module.exports = userRoutes;

主文件

//1.引入 express
const express = require('express');
//2.引入子路由文件
const homeRouter = require('./routes/homeRouter');
const userRouter = require('./routes/userRouter');
//3.创建 app 对象
const app = express();
//4.设置和使用中间件 配置路由的方式
//引入单个路由 可以设置第一个参数来配置路由 形成第一个参数和子路由的拼接 /user/userCenter
app.use('/user',homeRouter);
app.use(homeRouter);//引入单个路由
app.use(homeRouter,userRouter);//引入多个路由
//5.监听端口
app.listen(80,()=>{
console.log('80 端口启动....');
})

EJS

  1. 八、EJS
  • 1、EJS 单独使用
    下载安装 EJS npm i ejs --save
  	//1.引入ejs
    const ejs = require('ejs');
    //2.定义数据
    let person = ['张三','李四','王二麻子'];
    //3.ejs解析模板返回结构
    //<%= %> 是ejs解析内容的标记,作用是输出当前表达式的执行结构
    //ejs.render('<%= 输出的内容 %>',{键名:键值}) 返回的是一个字符串内容
    //render方法的第二个参数对象中的键名就是模板文件中的变量名
    //对象中的键值就是变量文件中的变量名对应的实际值
    let html = ejs.render(<%= person.join(",") %>, {person:person});
    //4.输出结果
    console.log(html);
  • 2、EJS 在 express 中的使用
    配置模板引擎 app.set('view engine','ejs');
    配置模板的存放目录 app.set("views","./views")
const express = require('express');
const app = express();
app.set('view engine','ejs');
//注意:创建的模板文件后缀需要是 ejs,且创建的位置需要在 views 文件夹里面
app.set('views',\_\_dirname + '/views'); //目录可以自定义
app.get('/',(request,response)=>{
	let zym = '细节决定成败';
	let stars = ['SHE','羽泉','beyond'];
	response.render('home',{zym,stars}); //第一个参数为模板文件名
});

后台获取form上传的文件

  • 安装 npm i formidable
  • 前端通过new FormData(formDOM元素)获取form表单中的数据
 //获取表单数据
 	let myformdata = new FormData(document.advForm);
	try {
	     //发送ajax请求
	     let result = await axios.post('/addAdv', myformdata);
	     toastr.success(result.message);
	     console.log(result)//获取后端返回的数据	      
	 } catch (e) {
	     toastr.error(e.msg);
	 }
  • 后端通过formidable获取前端传输的数据
//3、建立路由规则
//导入formidable
const formidable = require("formidable");
AdvRoutes.post("/addAdv", (request, response) => {
  // 创建表单对象,接收前端提交的数据
  const form = new formidable.IncomingForm({
    uploadDir: path.resolve(__dirname, "../uploads"), //设置文件上传的路径目录
    keepExtensions: true, //设置是否保留扩展名
    encoding: "utf-8", //设置提交的数据的编码格式
    maxFieldsSize: 2 * 1024 * 1024, //设置文件上传的最大限制
  });
  form.parse(request, async (err, fields, files) => {
    // files  图片上传相关的字段值
    // console.log('非图片以外的所有的字段值:', fields)
    // console.log('图片的新的文件名:', files.advPic.newFilename)

    //完成数据的添加
    let result = await advModel.create({
      ...fields,
      advImg: files.advPic.newFilename,
      createTime: nowTime(),
    });
    if (result) {
      response.json({
        code: 10000,
        message: "添加广告数据成功",
      });
    } else {
      response.json({
        code: 10001,
        message: "添加广告数据失败",
      });
    }
  });
});

express框架

一、什么是Express

Express是一个基于Node.js平台的极简、灵活的web应用开发框架,说白了,就是一个被封装好的npm的包,提供

了很多功能,封装了很多api,让我们在做web开发的时候,变得非常的便利,能够提高我们对于web开发应用的效

率,有了它,咱们在构建服务的时候就会变的很方便,尤其在请求响应的时候。

简单来说,Express就是运行在node中的用来搭建服务器的模块。

而且也是基于node.js中的http模块基础之上构建了自己的一些应用和语法。

官方网址:https://www.expressjs.com.cn/

二、Express的使用

2.1 Express的下载

npm i express --save   # 安装express并添加到依赖项

注意:安装的文件夹名称、package.json文件中的name;都不能与express重复;且需要先初始化init

2.2 Express的使用

  • 引入express框架

    const express = require('express'); # 返回值一个函数
    
  • 创建服务对象

    const app = express();  # 函数调用
    
  • 创建路由规则

    【根据用户的请求,来执行不同的回调】

    例如:

  app.get('/',(request,response)=>{  # 当请求方式为get,且请求路径为/,则执行该回调函数
      //响应的内容如果为中文,容易乱码,可以设置响应头
      response.setHeader('Content-type','text/html;charset=utf-8');
  	response.end('home首页')
  })
  app.get('/admin',(request,response)=>{  # 当请求方式为get,且请求路径为/admin,则执行该回调函数
  	response.end('admin管理页')
  })
  • 监听端口启动服务
  app.listen(80,()=>{
  	console.log('服务已经启动80端口监听中');
  })

三、Express的路由

3.1 什么是路由

路由是指如何定义应用的端点(URIs)以及如何响应客户端的请求,是由一个 URI、HTTP 请求(GET、POST等)

和若干个句柄组成的。

3.2 路由的定义

我们可以将路由定义为三个部分:

第一部分:HTTP请求的方法(get或post)

第二部分:URI路径

第三部分:回调函数

3.3 路由的实现

Express中提供了一系列函数,可以让我们很方便的实现路由。

	app.<method>(path,callback) 
  • method指的是HTTP请求方法,例如:app.get()、app.post()、app.all()
  • path指要通过回调函数来处理的URL地址,例如:/、/admin、/login、*
  • callback参数是应该处理该请求并把响应发回客户端的请求处理程序

例如:get请求

//1.引入express
const express = require('express');

//2.创建express对象
const app = express();

//3.创建路由规则
app.get('/',(request,response)=>{
     response.setHeader('Content-type','text/html;charset=utf-8');
     response.end('首页');
})

//4.监听端口并启动服务
app.listen(80,()=>{
    console.log('服务已经启动,80端口正在运行中');
})

例如:post请求

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <form action="http://127.0.0.1/login" method="post">
        用户名:<input type="text" name="username"/>
        <button>登录</button>
    </form>
</body>
</html>
//1.引入express框架
const express = require('express');

//2.创建express对象
const app = express();

//3.建立路由规则
app.post('/login',(request,response)=>{
        response.end('login');
});

//4.监听端口并启动服务
app.listen(80,()=>{
    console.log('80端口启动....');
})

例如:all请求

表示所有的请求方式均可。

app.all('/admin',(request,response)=>{
      response.end('admin page');
})

*:表示全局匹配路径的通配符,任何的请求路径均可。

app.all('*',(request,response)=>{
    response.statusCode = 404;
    response.end('<h1>404 Not Found</h1>');
})

3.4 请求参数的获取

利用express框架api来获取请求报文中的内容参数,express框架中获取请求数据的方式和原生的http模块是兼容的。

//引入express框架
const express = require('express');
//创建服务对象
const app = express();
//规则
app.get('/req',(request,response)=>{
    //请求方式
    console.log(request.method);
    //请求路径
    console.log(request.url);
    //http版本
    console.log(request.httpVersion);
    //请求头
    console.log(request.headers);
    
    
    //express提供的API
    //查询字符串
    console.log(request.query); // {a:1,b:2}
    
    //响应
    response.end('request');
    
});

app.listen(80,()=>{
    console.log('80端口启动....');
})

3.5 路由参数的设置以及获取

app.get('/:id.html	',(request,response)=>{
      //获取路由中的请求参数
      console.log(request.params.占位符名称)
}); 

四、express响应的设置

express框架中response使用的方式和原生的http模块是兼容的。

//引入express框架
const express = require('express');
//创建服务对象
const app = express();
//路由规则
app.get('/res',(request,response)=>{
	//响应状态码
    response.statusCode = 401;
    //响应状态字符串
    response.statusMessage = 'Error';
    //设置响应头
    response.setHeader('a','101');
    //设置响应体
    response.end('body');
    
    
    //express中独有的API响应
    response.send();
    /*
     * 区分end()和send()
     * 相同点:都是可以设置响应体
     * 不同点:send()除了设置响应体之外,还可以额外增加一个响应头
     * 相当于response.setHeader();
     * 如果响应的内容为中文的话,那么使用send则不会是乱码
    */
    
    //下载文件的响应
    response.download('文件路径'); //适合于软件、音乐、视频等文件的下载
    //其核心就是在response Headers中有一个Content-Disposition:attachment;filename="xx"
    
    //响应文件的内容
    response.sendFile(__dirname + '/文件的路径'); //注意这个路径必须是绝对路径
    
    //重定向
    response.redirect('login');
    //其核心就是在response Headers中有一个Location
    
    //响应状态码的设置
    response.status(400);
    //响应状态码的设置一定要伴随着响应体
    response.send('body');
});
//监听端口
app.listen(80,()=>{
    console.log('80端口启动....');
})

五、中间件

5.1 什么是中间件

Express是一个自身功能极简,完全是由路由和中间件构成一个web开发框架。

从本质上来说,一个Express应用就是在调用各种中间件。

中间件(Middleware)是一个函数,它可以访问请求对象(request)响应对象

(response)和web应用中处于请求-响应循环流程中的中间件,一般被命名为next的变量。

例如:我们可以举一个生活中的例子来更好的理解它:

在处理污水的时候,一般都要经过三个处理环节,从而保证处理过后的废水,达到排放标准。
在这里插入图片描述

处理污水的这三个中间处理环节,就可以叫做中间件。

当一个请求到达 Express 的服务器之后,可以连续调用多个中间件,从而对这次请求进行预处理。
在这里插入图片描述

例如现在我们定义一种需求:我们需要获取请求到达服务器的时间

如果我们不使用中间件的话,我们就需要在每一个路由中都进行单个的获取,这无疑非常的麻烦。

const express = require('express');
const app = express();
app.get('/',(request,response)=>{
	const time = Date.now();
	response.end('Home Page.');
});
app.get('/user',(request,response)=>{
	const time = Date.now();
	response.end('User Page.');
});
app.listen(80,()=>{
    console.log('http://127.0.0.1');
})

5.2 中间件的类型

  • 全局中间件
  • 路由中间件

5.3 定义全局中间件

每一次路由的请求到达服务端之后都要执行中间件 ,无论是否存在该路由规则,中间件函数都会执行。

let recordMiddleware = function(request,response,next){
	 //实现功能代码
	 //.....
	 //执行next函数(当如果希望执行完中间件函数之后,仍然继续执行路由中的回调函数,必须调用next)
	 next();
}

在这里插入图片描述

调用了next函数代表这个中间件处理完毕了,要交给下一个中间件或者路由去处理了。

一般情况下程序中必须要做的事情都会在全局中间件中设置。

app.use(recordMiddleware);
5.3.1 定义全局中间件的简化形式
app.use(function (request, response, next) {
    console.log('定义第一个中间件');
    next();
})

上面的案例就可以修改成

const express = require('express');
const app = express();
//定义全局中间件的简化形式
app.use((request,response,next)=>{
    //获取请求到达服务器的时间
    const time = Date.now();
    //然后再request请求对象身上挂载自定义属性,从而将时间共享到后面所有的路由
    request.startTime = time;
    next();
});
app.get('/',(request,response)=>{
	response.end('Home Page.' + request.startTime);
});
app.get('/user',(request,response)=>{
	response.end('User Page.' + request.startTime);
});
app.listen(80,()=>{
    console.log('http://127.0.0.1');
})
5.3.2 定义多个全局中间件

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

//1、引入express
const express = require('express');
//2、 创建服务对象
const app = express();
//5、创建中间件(全局中间件、路由中间件)

//5.1 定义全局中间件

app.use(function (request, response, next) {
    console.log('定义第一个中间件');
    next();
})
app.use(function (request, response, next) {
    console.log('定义第二个中间件');
    next();
}) 

//或者
/*let loginMiddleWare = (request, response, next) => {
    console.log('我是全局中间件1');
    next();
}

let login1MiddleWare = (request, response, next) => {
    console.log('我是全局中间件2');
    next();
}

app.use(login1MiddleWare, loginMiddleWare);*/

//3、创建路由规则
app.get('/login', (request, response) => {
    //判断
    response.end('login');
});
//4、设置端口
app.listen(80, () => {
    console.log('80端口正在运行中');
})

5.4 定义路由中间件

当想要某一些路由在请求的时候,需要中间件函数的支持,则就不需要设置全局中间件,而需要在路由规则中设置

不使用 app.use() 定义的中间件,也叫做局部生效的中间件。

app.get('/路由规则',`中间件函数`,(request,response)=>{
    
});
//1、引入express
const express = require('express');
//2、 创建服务对象
const app = express();
//3、定义中间件函数 m1
const m1 = function(request,response,next){
	console.log('这是中间件函数');
}
//4、创建路由规则
app.get('/',m1,(request,response)=>{
	response.end('Home Page');
});
//5、设置监听端口
app.listen(80,()=>{
    console.log('80端口正在启动中...');
})

如果需要多个中间件函数,那么就可以将所需要的中间件函数都列上

app.get('/路由规则',中间件函数1,中间件函数2,(request,response)=>{
    
});

写成数组的形式也是可以的。

app.get('/路由规则',[中间件函数1,中间件函数2..],(request,response)=>{
    
});

5.5 获取请求体数据 body-parser

5.5.1 注意事项
  • 如果请求方式为GET,咱们可以使用express中内置api(request.query)/ request.params

    • query:接受的是地址栏中的?的请求字符串的数据
    • params:接受的是url中的占位符的名称
  • 如果请求方式为POST,express中没有内置获取表单post请求体的API,这里咱们需要借助第三方包body-parser

5.5.2 使用方式

第一步:安装

npm i body-parser

第二步:导入body-parser包

const bodyParser = require('body-parser');

第三步:设置使用body-parser中间件

app.use(bodyParser.urlencoded({extended:false}));

第四步:使用request.body来获取请求体数据

切记:表单中元素必须要设置name属性,否则无法获取请求体数据

<body>
    <form action="http://127.0.0.1/login" method="post">
        <p>用户名:<input type="text" name="username"></p>
        <p>密码:<input type="password" name="userpass"></p>
        <p><button>登录</button></p>
    </form>
</body>
app.post('/login',(request,response)=>{
    //获取请求体数据
	//console.log(request.body);
    //用户名
    console.log(request.body.username); //admin
    //密码
    console.log(request.body.userpass); //123456
    response.send('获取请求体数据');
});

获取到的请求体数据:

[Object: null prototype] { username: 'admin', userpass: '123456' }

5.6 静态资源中间件的使用

静态资源:长时间不发生改变的资源,称之为静态资源,例如:css、js、img、font、html。

动态资源:内容经常发生改变的资源,称之为动态资源。

站点托管(静态资源托管static)
1、直接访问服务器地址时,会将static方法托管的文件夹中的index.html返回前端浏览器
2、只托管指定文件夹内的内容
3、用于托管服务器总的前端资源(前端代码)

//引入express框架
const express = require('express');
//创建服务对象
const app = express();
//静态资源中间件的设置,将当前文件夹下的public目录作为网站的根目录
app.use(express.static('./public'));  //当然这个目录中都是一些静态资源
//如果访问的内容经常变化,还是需要设置路由
//但是,在这里有一个问题,如果public目录下有index.html文件,单独也有index.html的路由,
//则谁书写在前,优先执行谁
app.get('/index.html',(request,response)=>{
    respsonse.send('首页');
});
//监听端口
app.listen(80,()=>{
    console.log('80端口启动....');
});

文件路径托管
1、all方法只能写在脚本最后
2、托管服务器根目录中的所有文件
3、访问时需要书写完整文件在服务器根目录中的地址
4、用于托管服务器资源(图片、视频、头像等)

app.all('*',(request,response)=>{
  console.log(request.url);// 资源地址url
  console.log(__dirname);//根目录路径
  response.sendFile(__dirname + request.url) //拼接的形式获得资源绝对路径
})

六、Router路由器

6.1 什么是Router

Router是一个完整的中间件和路由系统,也可以看做是一个小型的app对象。

6.2 为什么要使用Router

目的主要是为了更好的分类来管理我们的route。

6.3 Router的使用

目的:拆分路由代码

第一步:创建单独的路由文件,名称和位置都是自定义

子文件

  • 引入express框架
const express = require('express');
  • 创建路由对象
const route = express.Router();
  • 使用route对象代替app对象进行路由设置
route.get('路由名称',(request,response)=>{
	...
})
  • 暴露route对象
module.exports = route;

主文件

  • 在主文件中引入子模块文件,并设置中间件
//1.引入express
const express = require('express');
//2.引入子路由文件
const homeRouter = require('./routes/homeRouter');
//3.创建app对象
const app = express();
//4.设置和使用中间件
app.use(homeRouter);
//5.监听端口
app.listen(80,()=>{
    console.log('80端口启动....');
})

七、EJS模板引擎

9.1 什么是EJS

EJS是一个高效的Javascript的模板引擎。

模板引擎是为了使用户界面和业务数据(内容)分离而产生的。

简单来说,使用EJS模板引擎技能动态渲染数据,其核心就是一个npm的包

官网:https://ejs.bootcss.com/

9.2 EJS的使用步骤

  • 下载安装EJS
npm i ejs --save
  • 配置模板引擎
app.set('view engine','ejs');
  • 配置模板的存放目录
app.set("views","./views")
  • 在views目录下创建模板文件,例如:index.ejs
  • 使用模板,通过response来渲染模板
//1.引入ejs
const ejs = require('ejs');
//2.定义数据
let person = ['张三','李四','王二麻子'];
//3.ejs解析模板返回结构
//<%= %> 是ejs解析内容的标记,作用是输出当前表达式的执行结构
let html = ejs.render(<%= person.join(",") %>, {person:person});
//4.输出结果
console.log(html);

9.3 EJS的模板语法

  • 执行JS代码
<% code %>
  • 输出转义的数据到模板上
<%= code %>
  • 输出非转义的数据到模板上
<%- code %>
  • if判断
<%
    if(a==20){
%>
	<h3>a的值是20</h3>
<%
    }
%>
  • for循环
<%
	for(var i=0 ; i<3 ; i++){
%>
	<h3>a的值是20</h3>
<%
    }
%>

例1:循环输出我喜欢的水果

const ejs = require('ejs');
let fruits = ['苹果','香蕉','橘子'];
let str = fs.readFileSync(__dirname + '/html/page.html').toString();
let res = ejs.render(str,{fruits});
console.log(res);
<body>
    <ul>
		<% for(let i = 0;i<fruits.length;i++) { %>
   		 	<li><%= fruits[i] %></%></li>
    	<% } %>
    </ul>
</body>

例2:循环表格数据

/**
    搭建 HTTP 服务.
    GET  /table  响应一个表格 4 行 3 列表格, 并实现隔行换色 (JS)
 */
const data = [
    {
        id:1,
        name: 'gem',
        song: '野狼disco'
    },
    {
        id:2,
        name: '周杰伦',
        song: '不能说的密码'
    },
    {
        id:3,
        name:'林俊杰',
        song: '不为谁而作的歌'
    },
    {
        id:4,
        name: '五月天',
        song:'干杯'
    },
    {
        id: 5,
        name: '张艺兴',
        song: '莲'
    },
    {
        id:6,
        name:'刘德华',
        song:'冰雨'
    },
    {
        id: 7,
        name: '张学友',
        song: '情人'
    }
];
    
require('http').createServer((request, response) => {
    let body = '';    
    body += `<!doctype html>
    <html>
        <head>
            <title>歌曲列表</title>
            <meta charset="utf-8" />
            <style>
                table,td{
                    border-collapse: collapse;
                }
                td{
                    padding:20px 10px;
                }
            </style>
        </head>
        <body>
            <table border="1">
                <tr><td>ID</td><td>歌手名称</td><td>歌曲</td></tr>`;
    //根据数组的数据, 拼接 tr 标签内容
    data.forEach(item => {
        body += `<tr><td>${item.id}</td><td>${item.name}</td><td>${item.song}</td></tr>`;
    });

    body += `</table>
                </body>
            </html>`;
    //响应结果
    response.end(body);
}).listen(80);


获取读取页面

//1. 导入 ejs
const ejs = require('ejs');
//2、导入 fs
const fs = require('fs');
//3. 准备数据
const data = [
    {
        id:1,
        name: 'gem',
        song: '野狼disco'
    },
    {
        id:2,
        name: '周杰伦',
        song: '不能说的密码'
    },
    {
        id:3,
        name:'林俊杰',
        song: '不为谁而作的歌'
    },
    {
        id:4,
        name: '五月天',
        song:'干杯'
    },
    {
        id: 5,
        name: '张艺兴',
        song: '莲'
    },
    {
        id:6,
        name:'刘德华',
        song:'冰雨'
    },
    {
        id: 7,
        name: '张学友',
        song: '情人'
    }
];
let html = fs.readFileSync('./table.html').toString();
//4. 解析
const result = ejs.render(html, {data});
console.log(result);
<head>
    <title>歌曲列表</title>
    <meta charset="utf-8" />
    <style>
        table,
        td {
            border-collapse: collapse;
        }

        td {
            padding: 20px 10px;
        }
    </style>
</head>

<body>
    <table border="1">
        <tr>
            <td>ID</td>
            <td>歌手名称</td>
            <td>歌曲</td>
        </tr>
        <% for(let i=0;i<data.length;i++){ %>
            <tr>
                <td>
                    <%= data[i].id %>
                </td>
                <td>
                    <%= data[i].name %>
                </td>
                <td>
                    <%= data[i].song %>
                </td>
            </tr>
        <% } %>
    </table>
</body>

9.4 EJS在express中的使用

const express = require('express');
const app = express();
app.set('view engine','ejs');
//注意:创建的模板文件后缀需要是ejs,且创建的位置需要在views文件夹里面
app.set('views',__dirname + '/views'); //目录可以自定义
app.get('/',(request,response)=>{
    let zym = '细节决定成败';
	let stars = ['SHE','羽泉','beyond'];
    response.render('home',{zym,stars});  //第一个参数为模板文件名
});
座右铭:<span><%= zym %></span>
<ul>
    <% for(let i = 0; i<stars.length;i++) { %>
    	<li><%= stars[i] %></li>
    <%  } %>
</ul>

案例1:小册列表页的实现

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>小册列表</title>
    <link crossorigin='anonymous' href="https://cdn.bootcss.com/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
    <style>
        #container .no-margin-top{
            margin-top: 0;
        }
        .item{
            clear:both;
            height:auto;
            overflow: hidden;
            margin-bottom: 15px;
        }
    </style>
</head>
<body>
    <div class="container" id="container">
        <h2 class="page-header">小册列表</h2>
        <!-- 小册列表 -->
        <div class="row">
            <% for(let i=0;i<xiaoces.data.length;i++){ %>
            <div class="item">
                <div class="col-xs-2">
                    <img class="img-responsive" src="<%= xiaoces.data[i].base_info.cover_img %>" alt="">
                </div>
                <div class="col-xs-10">
                    <h4 class="no-margin-top"><a href="/book/<%= xiaoces.data[i].base_info.booklet_id %>"><%= xiaoces.data[i].base_info.title %></a></h4>
                    <p><%= xiaoces.data[i].base_info.summary %></p>
                    
                    <p class="price"><%= xiaoces.data[i].base_info.price / 100 %></p>
                </div>
            </div>
            <% } %>
        </div>

    </div>
    
</body>
</html>
const express = require('express');
const ejs = require('ejs');
const xiaoces = require('./data/xiaoce.json');
console.log(xiaoces);
const app = express();
app.set('view engine','ejs');
app.set('views','./view');
app.get('/',(request,response)=>{
    response.render('list',{xiaoces});
})
app.listen(80,()=>{
    console.log('80端口正在运行中...');
});

案例2:小册详情页的实现

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>小册详情页</title>
    <link crossorigin='anonymous' href="https://cdn.bootcss.com/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
    <!-- 顶部导航 start -->
    <nav class="navbar navbar-default">
        <div class="container">
          <!-- Brand and toggle get grouped for better mobile display -->
          <div class="navbar-header">
            <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
              <span class="sr-only">Toggle navigation</span>
              <span class="icon-bar"></span>
              <span class="icon-bar"></span>
              <span class="icon-bar"></span>
            </button>
            <a class="navbar-brand" href="#">Brand</a>
          </div>
      
          <!-- Collect the nav links, forms, and other content for toggling -->
          <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
            <ul class="nav navbar-nav">
              <li class="active"><a href="#">Link <span class="sr-only">(current)</span></a></li>
              <li><a href="#">Link</a></li>
              <li class="dropdown">
                <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Dropdown <span class="caret"></span></a>
                <ul class="dropdown-menu">
                  <li><a href="#">Action</a></li>
                  <li><a href="#">Another action</a></li>
                  <li><a href="#">Something else here</a></li>
                  <li role="separator" class="divider"></li>
                  <li><a href="#">Separated link</a></li>
                  <li role="separator" class="divider"></li>
                  <li><a href="#">One more separated link</a></li>
                </ul>
              </li>
            </ul>
            <form class="navbar-form navbar-left">
              <div class="form-group">
                <input type="text" class="form-control" placeholder="Search">
              </div>
              <button type="submit" class="btn btn-default">Submit</button>
            </form>
            <ul class="nav navbar-nav navbar-right">
              <li><a href="#">Link</a></li>
              <li class="dropdown">
                <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Dropdown <span class="caret"></span></a>
                <ul class="dropdown-menu">
                  <li><a href="#">Action</a></li>
                  <li><a href="#">Another action</a></li>
                  <li><a href="#">Something else here</a></li>
                  <li role="separator" class="divider"></li>
                  <li><a href="#">Separated link</a></li>
                </ul>
              </li>
            </ul>
          </div><!-- /.navbar-collapse -->
        </div><!-- /.container-fluid -->
    </nav>
    <!-- 顶部导航 end -->

    <!-- 内容部分 start -->
    <div class="container">
        <div class="col-xs-10 col-xs-offset-1">
            <div class="col-xs-3">
                <img class="img-responsive" src="<%= book.base_info.cover_img %>" alt="">
            </div>
            <div class="col-xs-9">
                <h4><%= book.base_info.title %></h4>
                <p><%= book.base_info.summary %></p>
                <p>价格: <%= book.base_info.price / 100 %></p>
                <p>销量: <%= book.base_info.buy_count  %></p>
            </div>
        </div>
    </div>
    <!-- 内容部分 end -->
</body>
</html>
const express = require('express');
const app = express();
app.set('view engine','views');
app.set('views',__dirname + '/views');
app.get('/book/:id',(request,response)=>{
     //获取路由参数
    const id = request.params.id;
    console.log(id);
    //根据id参数获取小册的详情内容
    let data = xiaoces.data.find(item=>{
        return item.booklet_id === id;
    });
    console.log(result);
    //响应结果
    response.render('detail',{book:result});
});
app.listen(80,()=>{
    console.log('80端口启动....');
})

八、hosts文件修改使用域名访问

hosts文件是本地域名解析的文件,而域名解析就是通过域名来获取与之对应的ip地址

文件地址:【C:\Windows\System32\drivers\etc\hosts】

找到这个文件打开,添加一条域名解析规则,然后就可以通过域名的方式来访问网站了。

127.0.0.1  网站的域名

但是默认情况下,计算机是不允许对该文件进行修改,需要对其设置权限

对hosts文件右键->属性->安全选项卡->编辑->Users->允许其所有权限

但是注意这种访问方式只能在本机使用,因为域名解析的ip地址是127.0.0.1。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值