Express框架:

一、   Express框架

Express框架是后台的Node框架,类似于JS中的jquery。

#原生Node开发会有很多问题:

1呈递静态页面很不方便,需要处理每个HTTP请求,还要考虑304问题

2路由处理代码不直观清晰,需要写很多正则表达式和字符串函数

3不能集中精力写业务,要考虑很多其他的东西

我们自己可以把第一天的作业,就是那个静态文件服务封装成为模块。封装的越多,就自己做出了类似Express的东西。

Express的哲学就是在你的想法和服务器之间充当薄薄的一层。这并不意味着它不够健壮,或者没有足够的有用特性,而是尽量少干预你,让你充分表达自己的思想,同时提供一些有用的东西。

http://www.expressjs.com.cn/

整体感知,Express框架:

1.expres惊艳的路由能力

var express = require('express');

var app = express();

app.get('/', (req, res) => {

res.send('你好');

});

app.get('/haha', (req, res) => {

res.send('这是haha页面,哈哈哈');

});

app.get(/^\/student\/([\d]{6})$/, (req, res) => {

//正则中的()表示分组提取 第[0]个

res.send('学生信息,学号' + req.params[0]);

});

//冒号可以被req得到

app.get('/teacher/:gonghao', (req, res) => {

//

res.send('老师信息,工号' + req.params.gonghao);

});

app.listen(2888);

 2.Express静态文件的伺服能力。

const express = require('express');

var app = express();

//使用中间件:(在当前目录的public文件夹下有index.html 这时GET / 的时候会自动读出index.html)

app.use(express.static('./public'));

app.get('/haha', (req, res) => {

res.send('haha');

});

app.listen(2888);

3.Express与模板引擎的配合,直观清晰,天呐撸

haha.ejs:

<!DOCTYPE html>

<html lang="en">

<head>

<meta charset="UTF-8">

<meta name="viewport" content="width=device-width, initial-scale=1.0">

<meta http-equiv="X-UA-Compatible" content="ie=edge">

<title>Document</title>

</head>

<body>

<h1>哈哈哈哈</h1>

<ul>

<% for(var i = 0;i<news.length;i++){%>

<li>

<%= news[i] %>

</li>

<% } %>

</ul>

</body>

</html>

3.js:

const express = require('express');

var app = express();

app.set('view engine','ejs');

app.get('/',(req,res)=>{

//默认就是views/文件夹下

res.render('haha.ejs',{

news:['我是小新闻啊','我也是啊','天啦噜']

})

});

app.listen(2888);

二、路由

我们学习的是Express4.x和Express3.x差别非常大。

用get请求访问一个网址

app.get(‘网址’,(req,res)=>{

});

app.post(‘网址’,(req,res)=>{

});

restful

如果想除了这个网址的任何methods的请求

app.all(‘/’,(req,res)=>{

})

app.get(‘/AAb’,(req,res)=>{

res.send(‘你好’);

})

实际上小写的访问也行。

所有的GET参数,?都已经被忽略。 锚点#也被忽略

你路由到/a,实际/a?id=2&sex=nan 也能被处理

正则表达式可以被使用。正则表达式中,未知部分用圆括号分组,然后可以用req.params[0]、req.params[1]来获取。

app.get(/^\/student\/([\d]{10})$/,(req,res)=>{

res.send(‘学生信息,学号’ + req.params[0]);

});

冒号是更推荐的写法。

const express = require('express');

var app = express();

app.get('/:username/:oid',(req,res)=>{

var username = req.params.username;

var oid = req.params.oid;

res.write(username);

res.end(oid);

});

app.listen(2888);

表单可以自己提交到自己:

05.js:

const express = require('express');

const app = express();

//设置模板引擎

app.set('view engine', 'ejs');

app.get('/', (req, res) => {

res.render('form');

});

app.post('/', (req, res) => {

//将数据添加进入数据库

res.send('成功');

});

app.listen(2888);

适合进行RESTful路由设计。

RESTful路由设计

/students

get 读取学生信息

post 修改学生信息

delete 删除学生信息

【用express来实现非常简单】

app.get、app,post、app,delete...

总结:这节课比较重点的地方是 路由,路由的话,app.get(‘\’)这里面可以写正则表达式,用()来捕获,也可以写:,最后用req.params[0] 或者req.params.xxx来获取,推荐的是使用:冒号的方式。

一、          中间件

//这个就叫做中间件

app.get('/',(req,res)=>{

console.log('2');

});

顾名思义,中间件(middleware)作为请求和响应之间的中间人,用于处理HTTP请求,返回特定结果。

如果我的get、post回调函数中,没有next参数,那么匹配上第一个中间件后就不会往下继续匹配了,如果向往下匹配的话,那么需要写next();

app.get('/',(req,res,next)=>{

console.log('1');

next();

});

//这个就叫做中间件

app.get('/',(req,res)=>{

console.log('2');

});

下面两个路由,感觉没有关系:

app.get('/:username/:id', (req, res) => {

console.log('1');

res.send('用户信息'+req.params.username);

});

//这个就叫做中间件

app.get('/admin/login', (req, res) => {

console.log('2');

res.send('管理员登陆');

});

但是实际上冲突了,因为admin可以当作用户名 login可以当作id。

解决方法1:交换位置,也就是说,express中所有的路由(中间件)的顺序至关重要。

匹配上第一个,就不会往下匹配了。具体的网上写,抽象的往下写。

主要规则:(写路由表的时候,越具体的越要往上写,越抽象的越要往下写)

解决方法2:使用next()

const express = require('express');

var app = express();

var a = 100;

//这个就叫做中间件

app.get('/admin/login', (req, res) => {

var username = req.params.username;

//检索数据库,如果username不存在,那么next

if(检索数据库){

console.log('2');

res.send('管理员登陆');

}

else{

next();

}

});

app.get('/:username/:id', (req, res) => {

console.log('1');

res.send('用户信息'+req.params.username);

});

app.listen(2888);

路由get、post这些东西,就是中间件,中间件讲究顺序,匹配上第一个之后就不会往后匹配了。除非写了next()之后才能够继续往后匹配。

app.use:

举例,如果我GET /admin 返回’hello world’ 那么我GET /admin/asd 也会返回’hello world’.

app.use('/admin', function(req, res, next) {

// GET 'http://www.example.com/admin/new/asd/asd'

console.log(req.originalUrl); // '/admin/new'

console.log(req.baseUrl); // '/admin'

console.log(req.path); // '/new/asd/asd'

next();

});

app.use也是一个中间件,它与get和post的不同是,它的网址不是精确匹配的,而是有拓展的。

所以:

app.use(‘/’,(req,res)=>{

})

//这样就会出现骚操作。所有的请求是/的扩展,所以…

但是要写next();否则会卡在这个中间件。

app.use(‘/’,(req,res)=>{

console.log(‘haha’);

next();

})

还可以这样简写:

//不写就相当于‘/’

app.use((req,res)=>{

console.log(‘haha’);

next();

})

app.use()就给我们增加一些特定功能的便利场所。

自带的静态服务:

app.use(express.static(‘./public’));

//使用了app.use这个方法,使用了封装好的express.static这个中间件,这个静态服没有next方法(),一般把它放在代码的上边部分,防止做路由的时候和现有文件冲突,

比如你有一个image文件夹就没必要再做/image路由转到别的地方。直接读这个文件夹就好了。

//其实似乎这两个广义地讲都叫中间件..

(但是我们其实编程时候不怎么使用app.use方法,因为这很不MVC)

app.use(‘/jingtai’,express.static(‘./public’));

·大多数情况下,渲染内容用res.render(),将会根据views中的模板文件进行渲染。如果不想使用view文件夹,想自己设置文件夹名字,那么app.set(‘views’,’…’)

·如果想写一个快速测试页,当然可以使用res.send()。这个函数 将根据内容,自动帮我们设置了Content-Type头部和200状态吗。send()只能用一次,和end一样。和end不一样在哪里?能够自动设置MIME

·如果想使用不同的状态吗,可以:

res.status(404).send(‘Sorry,we cannot find that’)

·如果想使用不同的Content-Type,可以:

res.set(‘Content-Type’,’text,html’);

app.set…

(…这些都可以被set,如果需要使用请详细查看官网文档)

四、GET请求和POST请求

·GET请求的参数在URL中,在原生Node中,需要使用url模块来识别参数字符串。在Express中,不需要使用url模块来parse了,可以直接使用req.query对象。

·POST请求在express中不能直接获得,必须使用body-parser模块,使用后,将可以用req.body得到参数。但是如果表单中含有文件上传,那么还是需要使用formidable模块。

req.query打印出的是一个对象,比如GET \?a=1&b=2 返回的就是:{a:1,b:2}

POST引擎需要引用body-parser中间件

req.body打印出一个对象

12.js:

const express = require('express');

var app = express();

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

app.set('view engine', 'ejs');

app.get('/', (req, res) => {

res.render('form');

});

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

app.post('/', (req, res) => {

res.send(req.body);

});

app.listen(3333);

捋捋api:

主要来看一下最后一个Route,Route是个啥.

以下内容摘抄自网络:

———————————————————————————————————————

当你调用 express() 方法时,就创建了一个 Application。事实上这个 Application 也只不过是对 Router 的一个轻量级封装而已。

每个 Application 内部都创建了一个 Router,大部分对 Application 的操作实际上都被重定向到了这个内部的 Router 上而已。而 Application 所做的,只不过是在这个 Router 的基础上添加了一些额外的便捷 API 而已。

举个例子,当你调用 app.get(...) 或者 app.use(...) 的时候,实际上真正调用的是 app._router.get(...) 或者 app_router.use(...)。

所以,Application 和 Router 的区别便很清楚了,Application 是 Router 的一个“包装”,而 Router 才是“核心”。

router.get is only for defining subpaths. Consider this example:

var router = express.Router();
 
app.use('/first', router); // Mount the router as middleware at path /first
 
router.get('/sud', smaller);
 
router.get('/user', bigger);

Now if you will open /first/sud in your browser, then smaller function will get called. If you will open first/user, then bigger will gets called. In short, app.use('/first', router) mounts the middleware at path /first, then router.get sets the subpath accordingly.

But if we instead use:

app.use('/first', fun);
 
app.get('/sud', bigger);
 
app.get('/user', smaller);

Now if you will open /first in your browser then fun will get called and for /sud, bigger will get called and for /user, the function smaller will get called. ...but remember here for /first/sud, no function will get called.

回答者要传达的意思是:“路由级别的中间件,可以作为app级别的中间件的扩展,从而减小app级别路径处理的臃肿,提高可维护性和扩展性”。

强行比喻一下:

产品经理通过应用级别的中间件,控制一级路径;然后各个项目经理,在此基础上,自己通过路由级别的中间件,控制二级路径(项目经理不用考虑产品经理是怎么处理一级路径的)。

——————————————————————————————————

小小相册项目:

//前端语言与后端语言

本质区别:前端是在用户电脑运行,后端是在服务器运行

Node中全是回调函数,所以我们自己封装的函数,里面如果有异步方法,比如I/O,那么就要用回调函数的方法封装。

错误

res.render(“index”,

{“name”:student.getDetailById(234234).name});

正确

student.getDetailByXuHao(234234,function(detail){

res.render(“index”,{

“name”:detail.name

})

})

Node_进阶_3的更多相关文章

  1. Node_进阶_8

    Node进阶第八天 一.复习 Node.js特点:单线程.异步I/O(非阻塞I/O).事件驱动(事件环). 适合的程序:就是没有太多的计算,I/O比较多的业务. 举例:留言本.考试系统.说说.图片裁切 ...

  2. Node_进阶_7

    Node进阶第七天 一.复习 一.索引   数据库中,根据一个字段的值,来寻找一个文档,是很常见的操作.比如根据学号来找一个学生.这个学号是唯一的.只要有学号,就能唯一确认一个学生的文档.学号这个属性 ...

  3. Node_进阶_6

    Node进阶第六天 一.复习 cookie是在res中设置,req中读取的.第一次的访问没有cookie. cookie的存储大小有限,kv对儿.对用户可见,用户可以禁用.清除cookie.可以被篡改 ...

  4. Node_进阶_5

    Node进阶第五天 为什么mysql不用开mongod –dbpath xx… 答:因为mysql会在”服务”中运行,也就是开机时自动启动并且长久驻扎在内存中了. mongodb其实也能通过设置来设成 ...

  5. Node_进阶_4

    Node进阶第四天 一.传统数据库技术回顾 数据库就是存储数据的,那么存储数据用txt就行了啊,为什么要有数据库? 理由之一:数据库有行.列的概念,数据有关系,数据不是散的. 老牌数据库,比如Mysq ...

  6. React-Native进阶_3.触摸高亮显示TouchableHighlight

    在安卓原生ListView  点击 其中一个子视图时,会有高亮效果,这个效果在ReactNative 中通过TouchableHighlight 实现,具体使用如下 4.触摸高亮显示 Touchabl ...

  7. Node_进阶_2

    第二天 一.复习: Node.js开发服务器.数据.路由.本地关心效果,交互. Node.js实际上是极客开发出的一个小玩具,不是银弹.有着别人不具备的怪异特点: 单线程.非阻塞I/O.事件驱动. 实 ...

  8. Node_进阶_1

    第一天 1.1简介 Node.js简介 V8引擎本身就是用于Chrome浏览器的JS解释部分,Ryan Dahl把这个V8搬到了服务器上,用于做服务器的软件. Node.js是一个让Javascrip ...

  9. PythonI/O进阶学习笔记_3.2面向对象编程_python的继承(多继承/super/MRO/抽象基类/mixin模式)

    前言: 本篇相关内容分为3篇多态.继承.封装,这篇为第二篇 继承. 本篇内容围绕 python基础教程这段: 在面向对象编程中,术语对象大致意味着一系列数据(属性)以及一套访问和操作这些数据的方法.使 ...

随机推荐

  1. Appstore排名前十的程序员应用软件

    程序员又名程序猿,苦逼劳累的代名词,曾经一个朋友这么开玩笑说,如果你是富二代,你当程序员就是脑残,如果你是穷二代,当程序员的话,死的时候一定是趴键盘. 程序员 哦,可怜的程序员.在那山的这边海的那边有 ...

  2. 【前端分享】 JavaScript最经典的55个技巧(转)

    从别的地方看到的,保存下,有空实践下再补充. 1. oncontextmenu="window.event.returnValue=false" 将彻底屏蔽鼠标右键 <tab ...

  3. 优动漫结合Photoshop怎么画草地?

    今天继续技法教学~草地的技法,PS教学~但是很简单,都是默认工具,而且是常用工具VS常用设置.你肯定会学会的! 草地教程,就到这里啦!有兴趣的可以尝试画一画哦,想要Get到更多有关优动漫的信息包括软件 ...

  4. DHCPv6,IPv6的有状态自动配置

    DHCPv6,IPv6的有状态自动配置 DHCPv6的工作原理与DHCPv4极其相似,但有一个明显的差别,那就是支持IPV6新增的编址方案.DHCP提供了一些自动配置没有的选项.在自动配置中,根本没有 ...

  5. Django框架 part 2

    web 框架本质 我们可以这样理解:所有的Web应用本质上就是一个socket服务端,而用户的浏览器就是一个socket客户端. 这样我们就可以自己实现Web框架了. 半成品自定义web框架 impo ...

  6. luogu P3387 【模板】缩点_拓扑排序

    还是很好些的. Code: #include <stack> #include <cstdio> #include <algorithm> #include < ...

  7. JS对以对象组成的数组去重

    这是从https://segmentfault.com/q/1010000006954351参考的,达到了我要去重的功能!!! var hash = {};//arr是要去重的对象数组 arr = a ...

  8. javascript编程风格(粗略笔记)

    1.空格 紧凑型: project.MyClass = function(arg1, arg2){ 松散型: for( i = 0; i < length; i++ ){ 2.代码行长度 最多8 ...

  9. POJ 3122 Pie( 二分搜索 )

    链接:传送门 题意:一个小朋友开生日派对邀请了 F 个朋友,排队上有 N 个 底面半径为 ri ,高度为 1 的派,这 F 个朋友非常不友好,非得"平分"这些派,每个人都不想拿到若 ...

  10. HDU 1828 Picture (线段树:扫描线周长)

    依然是扫描线,只不过是求所有矩形覆盖之后形成的图形的周长. 容易发现,扫描线中的某一条横边对答案的贡献. 其实就是 加上/去掉这条边之前的答案 和 加上/去掉这条边之后的答案 之差的绝对值 然后横着竖 ...