1 项目开发步骤
- 生成package.json文件;如
npm init --y
; - 安装模块文件;如:
npm install express --save-dev
; - 创建服务器文件:命令:
touch server.js
,创建server.js文件;
2 express三步走
- 引入模块,创建服务器:
const app=express()
- 添加监听:
app.listen(8080)
- 添加强求: app.get("/") app.post("/:admin/:id") app.use("/")
3 express整体感知
- 强大的路由:
- 可以用比较严格的路由;如:
/admin
- 可以自己手动给路由写正则表达式:
/^\/student\/(\d{6})$/
; 取参数:req.params[0]; - 可以使用express自己提供的路由:"/student/:id";取参数:req.params.id;
- 可以用比较严格的路由;如:
- 静态资源服务:
app.use(express.static("./public"))
;将所有静态资源放在public的目录下;打开所有的静态文件; - 可以跟模板配合使用,需要两步
- 设置模板引擎:
app.set("view engine","ejs")
;常用模板引擎:ejs,jade; - 通过res来渲染模板到浏览器:
res.render("index",{n:8})
;注意:express中默认把模板都放在views目录下;./views/
可以省略;index.ejs后缀名也可以省略;
- 设置模板引擎:
4 get请求
- 原生node中,如何接收get请求的参数?
- 用url模块:
url.parse(req.url,true).query
;
- 用url模块:
- 在express中,如何接收get请求的参数?
- 代码:
req.query
;获取参数对象;
- 代码:
- ejs代码:
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <title>表单get提交</title> </head> <body> <form action="/admin" method="get"> <label for="user"> 用户名:<input type="text" id="user" name="username" value="guomushan"> </label><br/> <label for="pass"> 密码:<input type="text" id="pass" name="password" value="0525"> </label><br/> <input type="submit" value="提交"> </form> </body> </html>
- get请求服务器代码:
const express=require("express"); const app=express(); app.listen(8080); //设置模板引擎; app.set("view engine","ejs"); //1.地址栏发送get请求,请求地址为/;然后打开form.ejs文件; app.get("/",function (req,res) { res.render("form"); }); //2.在form表单中,action请求地址与get请求地址相同;这样就会进入请求; app.get("/admin",function (req,res) { console.log(req.query);//{ username: 'guomushan', password: '0525' } res.send("提交成功"); });
5 post请求
- 原生node中,接受post请求的参数:
var str=""; req.on("data",function(data){ str+=data; } req.on("end",function(){ var postData=querystring(str);//拿到对象格式的数据; }
- express中,如果请求的是普通数据的话,用body-parser这个模块;如果请求的数据包含大文件(音频,视频,图片,word等),用formidable模块;
- 使用body-parser三部曲:
- 引入模块 bodyParser=require("body-parser");
- 设置中间件
app.use(bodyParser.urlencoded({extended:false}))
; - 通过req.body拿到前端通过请求体提交过来的数据;
- 代码:
- form表单代码:
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <title>表单post提交</title> </head> <body> <h2>post提交请求</h2> <form action="/admin" method="post"> <label for="user"> 用户名:<input type="text" id="user" name="username" value="guomushan"> </label><br/> <label for="pass"> 密码:<input type="text" id="pass" name="password" value="0525"> </label><br/> <input type="submit" value="提交"> </form> </body> </html>
- post-server服务器代码:
const express=require("express"); const bodyParser=require("body-parser"); const app=express(); app.listen(8080); //设置模板引擎 app.set("view engine","ejs"); //1.通过get请求,在页面中渲染表单 app.get("/",function (req, res) { res.render("form-post"); }); //设置中间件,使用bodyParser必须设置中间件,否则不能拿到数据; app.use(bodyParser.urlencoded({ extended: false })); //2.利用post请求,获取参数 app.post("/admin",function (req, res) { console.log(req.body); res.send("提交成功"); });
6 use请求
- use请求可以扩充地址;地址不严格;
- 格式代码:
app.use("/admin",function(req,res){})
-
req.originalUrl
:拿到的是:包括基本地址的所有请求地址; -
req.baseUrl
:拿到的是:基本地址/admin",如路由地址相同; -
req.path
:拿到的是:不包括基本地址,也不包括参数的其余地址; -
req.url
:拿到的是:不包括基本地址的所有请求地址; - 代码:
app.use("/admin",function (req, res) {
//地址栏请求地址:http://localhost:8080/admin/aaa/bbb/index.js?name=guo&age=26
//1.req.url拿到的是/admin后面的地址;
console.log(req.url);//打印结果:/aaa/bbb/index.js?name=guo&age=26
//2.req.originalUrl拿到真正的请求地址和传给后台的参数;
console.log(req.originalUrl);//打印结果:/admin/aaa/bbb/index.js?name=guo&age=26
//3.req.baseUrl拿到的是基本的地址,与路由地址一致;
console.log(req.baseUrl);//打印结果:/admin
//4.req.path拿到的是除了基本地址的其他子子孙孙的路径地址;(不包含基本地址,也不包含参数)
console.log(req.path);//打印结果:/aaa/bbb/index.js
res.send("ok");
});
7 中间件middleware
- 路由get,post这些东西;就是中间件,中间件讲究顺序,匹配上第一个之后,就不会往后匹配了;next函数才能够继续往后匹配;所以,get和post对路由卡的很死;
- 解决方式1:写路由的时候,具体的往上写,抽象的往下写;
app.get('/admin/login',function (req,res) { console.log('2'); res.send('管理员登录');//send后面不能写任何代码;会报错; }); app.get('/:username/:id',function (req,res,next) { console.log('1'); res.send('管理员登录'+req.params.username) });
- 解决方式2:配合数据库,进行条件判断,数据库中存在的进行if条件;不存在进行else,执行next(),进而执行其他的代码;
const express=require("express"); const app=express(); app.listen(8080); //简单的数据库 var user={ teacher:["guo","bin"], student:88 }; //先执行上面代码;然后进行条件判断;如果不满足,在向下进行代码; app.get("/:username/:pass",function (req, res,next) { var username=req.params.username; if(user[username]){ res.send("我是普通用户"); }else{ next(); } }); app.get("/admin/login",function (req, res,next) { res.send("我是管理员"); });
- app.use()也是一个中间件,与get和post不同的是,他的网址不是精确匹配的,而是能够有小文件夹拓展的;如下;
- 当你不写路径的时候,就相当于'/',即相当于所有网址;
- 所以,一般用use当接盘侠;
// GET 'http://www.example.com/admin/new' app.use('/admin',function (req,res) { console.log(req.originalUrl); // '/admin/new' console.log(req.baseUrl); // '/admin' console.log(req.path);// '/new' res.send('你好') });
8 send
- send跟原生node中end的区别:
- send里面既可以传字符串和buffer;也可以传json对象;
- 原生node中end和write里面只能传字符串和buffer;
- send跟render的区别:
- send一般用来测试;render一般用来渲染页面;
- send可以用来配合状态码的输出:
res.status(404).send("文件没找到")
;其中状态码发送到前端浏览器中在控制台中呈现;
9 设置浏览器中文件的渲染类型
- 原生node中通过:
res.writeHeader(200,{"Content-Type":"text/html;charset=UTF-8"})
- 在express中通过:
res.set("Content-Type","text/html")
;