Koa – Node.js框架学习@郝晨光
本文由郝晨光整理总结并编写,未经允许禁止转载。
前言
学习koa,我之前学习过express,但是在使用express的时候,还是一直使用的回调函数的方式来解决异步,现在想想真是恐怖,后来理解到koa这个框架,它相对于express来说,小巧了很多,对于异步的解决也变得更加优雅了。用官方的话来说,koa是基于Node.js平台的下一代web平台开发框架。
Image 3.png
正文
首先一定要先开始一个新的项目,新建一个文件夹
在文件夹目录中,使用命令提醒符执行
npm init -y,初始化package.json文件;安装
- Koa 依赖 node – v7.6.0 或者 ES2015及更高版本和 async 方法支持。
- 先查看node的版本
node -v; - 而后执行
npm install koa进行安装;
使用
- 新建index.js;
- 先上官网上最经典的hello wrold案例;
const Koa = require('koa');const app = new Koa();app.use(async ctx => { ctx.body = 'hello word!'})app.listen(8000, () => { console.log('Koa server listen in http://localhost:8000/');})- 打开浏览器,输入
localhost:8000/,即可以看到我们的页面上显示了hello world!; - 那我们的第一个koa应用就已经运行起来了~。
读取 HTML 页面
- 在Koa中,我们假如要使用 HTML 应该怎样做呢?
- 在原生nodejs或者者express中,我们使用的是fs板块,而后使用回调函数,一层套一层;
- 在Koa中,我们仍旧使用fs板块,但是,要对fs板块的读取文件,进行进一步的封装;
- 在目录下,我们新建一个
index.html,并随意写一点东西; - 接着开始我们渐行渐远的程序生涯;
const Koa = require('koa');const fs = require('fs');const app = new Koa();function readFile(url) { return new Promise((resolve, reject) => { fs.readFile(url, (err,file) => { if(err) { reject(err); }else { resolve(file); } }) })}app.use(async ctx => { ctx.response.type = 'html'; // 重点 ctx.body = await readFile('index.html');})app.listen(8000, () => { console.log('Koa server listen in http://localhost:8000/');})// 本文由郝晨光整理总结并编写,未经允许禁止转载。- 可以看到,我们利用Promise将fs板块的readFile方法进行了二次封装,读取了本地的index.html文件
- 重点的地方我已经标出来了,为什么要标重点呢?
- 由于在Koa中,ctx.body默认返回的类型是
text/plain;而我们要返回html文件,所以应该在返回文件之前,设置好返回类型,让用户端可以正确的接收; - 而后我们使用
async + await组合,在数据读取完成之后,返回读取的文件; - 最后,打开浏览器,可以看到浏览器上输出的就是我们
index.html文件中写的内容
读取静态资源
- html文件我们已经可以正确的读取并返回了,在我们的页面上,避免不了会使用很多的静态资源,例如css、js、image、font等等;这些静态资源我们应该怎样解决呢?
- 在这里,我们使用一个Koa的中间件
koa-static - 在命令提醒符中执行
npm install koa-static; - 接着书写我们的程序
// ~~ 省略 ~~const app = new Koa(); // 新建koa对象const KoaStatic = require('koa-static'); // koa静态文件读取app.use(KoaStatic(__dirname)); // 使用中间件// ~~ 省略 ~~- 接着,打开我们的浏览器,可以看到静态资源已经可以正确的请求到了;
- 当然了,这个时候,我们可以把之前返回html文件时设置响应类型的一步省略掉了,由于
koa-static已经帮我们做了这件事了。
定义路由
- 所谓的路由,就是根据不同的请求路径,响应不同的内容;
- 在Koa中,我们可以定义原生路由,也可以使用封装好的路由中间件;
- 先看一下原生路由的写法吧!
app.use(async ctx => { if(ctx.request.method==='GET') { // GET请求 switch (ctx.request.path) { case '/': // 匹配默认路由 ctx.body = await readFile('index.html'); // 返回index.html文件 break; case '/about': // 匹配/about路由 ctx.body = 'about路由页面'; // 返回about路由页面 break; default: ctx.body = await readFile('index.html'); // 默认返回index.html文件 break; } }else if(ctx.request.method==='POST') { // POST请求 switch (ctx.request.path) { default: ctx.body = 'post 请求'; // 响应post请求 break; } }});//本文由郝晨光整理总结并编写,未经允许禁止转载。可以看到我上边写的,对请求方式以及路由进行了解决,在不同的请求方式,不同的请求路径下,执行不同的操作,响应不同的结果。
原生路由
路由中间件
- 我们使用原生方式定义路由,未免有些太过繁琐,并且代码不便于阅览和维护;所以,建议使用中间件的方式进行路由配置。
- 我这里使用的是 koa-router 这个中间件,当然,koa的路由中间件不是只有这一种。
- 在命令提醒符中安装
npm install koa-router; - 接着,进行我们的程序生涯;
// ~~ 省略 ~~const KoaRouter = require('koa-router');const router = new KoaRouter();router.get('/',async ctx => { ctx.body = await readFile('index.html');});router.get('/about',async ctx=> { ctx.body = 'about路由页面'});router.post('/form',async ctx => { ctx.body = 'post请求'});app.use(router.routes());// ~~ 省略 ~~- 打开页面,并进行路由切换,可以看到没有任何疑问;
但是这样所有的路由配置都写在了index.js中,不利于维护,所以我们要将路由内容和公用方法提取出来。
路由中间件
代码板块化
- 首先对路由进行板块化
- 在目录下新建routes文件夹,并新建home.js,用来存放关于首页的少量路由配置。
- 将上边的路由代码单独写到home.js中,并抛出,如下:
- home.js
const KoaRouter = require('koa-router');const router = new KoaRouter();router.get('/',async ctx => { ctx.body = await readFile('index.html');});router.get('/about',async ctx=> { ctx.body = 'about 路由'});router.post('/from',async ctx => { ctx.body = 'post请求'});module.exports = router;- index.js
const homeRouter = require('./routes/home');app.use(KoaStatic(__dirname));app.use(homeRouter.routes());- 在index.js中,直接引入使用就可,和原有代码没有任何区别。
- 需要注意的是,对于功能中间件,例如
koa-static这种,我们应该放在路由中间件之前。 - 否则的话可能会出错,在路由中不能正确的读取静态文件等。
二级路由
- 已经学会了一级路由的定义,我们趁热打铁,学习二级路由
- 在routes目录下,新建user.js,定义客户路由
// user.jsconst KoaRouter = require('koa-router');const router = new KoaRouter({ prefix: '/user'});router.get('/',async ctx => { ctx.body = '客户界面'});router.get('/:id',async ctx => { ctx.body = '客户介绍'+ctx.params.id;});router.post('/login',async ctx => { ctx.body = '客户注册成功!'});module.exports = router;// index.js// ~~ 省略 ~~const userRouter = require('./routes/user');// ~~ 省略 ~~app.use(userRouter.routes());接着,打开浏览器,我们测试一下我们的二级路由,是没有任何疑问的。
二级路由.gif
post请求解决
- 我们都知道,使用post请求一般用来提交表单,或者者修改数据等。而post请求中的数据,存放在请求体中,使用原生Node的方法的话,我们需要监听原生req对象上的data方法以及end方法,并将数据格式转化。而express中,我们有一个
body-parser的插件可以使用。 - 那么在Koa中,我们应该使用什么呢?
- 在Koa中,我们使用
koa-bodyparser这个中间件来解决post请求的数据 - 在命令提醒符安装
npm install koa-bodyparser; - 接着我们在index.js中使用这个中间件;
- 加入下面两行代码,与原价使用
koa-static中间件位置一样就可; const KoaBodyParser = require('koa-bodyparser');app.use(KoaBodyParser());- 使用了这个中间件,我们即可以在
ctx.request.body中拿到post请求的数据了; router.post('/login',async ctx => { ctx.body = ctx.request.body; });- 接着改造一下我们的html文件,提交一下表单;
<form action="/user/login" method="post"> 姓名:<input type="text" name="name" autocomplete="off"/> <br> <input type="radio" name="sex" value="男"/>男 <input type="radio" name="sex" value="女"/>女 <input type="submit" value="提交form"> </form>可以看到,表单提交正常,我们也正确的拿到了表单提交的数据。
Koa提交表单
- 我们都知道,使用post请求一般用来提交表单,或者者修改数据等。而post请求中的数据,存放在请求体中,使用原生Node的方法的话,我们需要监听原生req对象上的data方法以及end方法,并将数据格式转化。而express中,我们有一个
CORS跨域配置
- 在我们现在的服务器生涯中,避免不了要使用跨域,特别是CORS跨域。
- 那么,在Koa中,我们应该怎样去设置跨域呢?
- 我们可以使用中间件,也可以使用原生方法手写。
- 老规矩,先看原生方法。
app.use(async (ctx, next) => { // 允许来自所有域名请求 ctx.set("Access-Control-Allow-Origin", "*"); // 这样就能只允许 http://localhost:8080 这个域名的请求了 // ctx.set("Access-Control-Allow-Origin", "http://localhost:8080"); // 设置所允许的HTTP请求方法 ctx.set("Access-Control-Allow-Methods", "OPTIONS, GET, PUT, POST, DELETE"); // 字段是必须的。它也是一个逗号分隔的字符串,表明服务器支持的所有头信息字段. ctx.set("Access-Control-Allow-Headers", "x-requested-with, accept, origin, content-type"); // 服务器收到请求以后,检查了Origin、Access-Control-Request-Method和Access-Control-Request-Headers字段以后,确认允许跨源请求,即可以做出回应。 // Content-Type表示具体请求中的媒体类型信息 ctx.set("Content-Type", "application/json;charset=utf-8"); // 该字段可选。它的值是一个布尔值,表示能否允许发送Cookie。默认情况下,Cookie不包括在CORS请求之中。 // 当设置成允许请求携带cookie时,需要保证"Access-Control-Allow-Origin"是服务器有的域名,而不能是"*"; ctx.set("Access-Control-Allow-Credentials", true); // 该字段可选,用来指定本次预检请求的有效期,单位为秒。 // 当请求方法是PUT或者DELETE等特殊方法或者者Content-Type字段的类型是application/json时,服务器会提前发送一次请求进行验证 // 下面的的设置只本次验证的有效时间,即在该时间段内服务端可以不用进行验证 ctx.set("Access-Control-Max-Age", 300); /* CORS请求时,XMLHttpRequest对象的getResponseHeader()方法只能拿到6个基本字段: Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma。 */ // 需要获取其余字段时,使用Access-Control-Expose-Headers, // getResponseHeader('myData')可以返回我们所需的值 ctx.set("Access-Control-Expose-Headers", "myData"); await next(); })- 原生方法来自:node.js 应答跨域请求实现(以koa2-cors为例)
- 接着我们来看中间件吧!
- 在Koa2中,我们使用
koa2-cors这个中间件来设置CORS跨域请求。 - 先安装
npm install koa2-cors; - 接着,在index.js中使用。
const KoaCors = require('koa2-cors');// ~~ 省略 ~~// CORS跨域app.use(KoaCors({ origin: ctx => { return ctx.request.header.origin; }, exposeHeaders: ['WWW-Authenticate', 'Server-Authorization'], maxAge: 5, credentials: true, allowMethods: ['GET', 'POST', 'DELETE', 'OPTIONS'], allowHeaders: ['Content-Type', 'Authorization', 'Accept', 'Origin'],}));//本文由郝晨光整理总结并编写,未经允许禁止转载。- 特别需要注意的是,在
app.use()使用koa2-cors的时候,我们应该把它放在别的中间件的前边,特别是静态资源解决和路由解决中间件的前边,这样可以保证我们在跨域请求静态资源的时候不会出问题。
假如本文对您有帮助,可以看看本人的其余文章:
前台常见面试题(十三)@郝晨光
前台常见面试题(十二)@郝晨光
前台常见面试题(十一)@郝晨光
结言
感谢您的查阅,本文由郝晨光整理并总结,代码冗余或者者有错误的地方望不吝赐教;菜鸟一枚,请多关照
说明
1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是摆设,本站源码仅提供给会员学习使用!
7. 如遇到加密压缩包,请使用360解压,如遇到无法解压的请联系管理员
开心源码网 » Koa – Node.js框架学习@郝晨光
1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是摆设,本站源码仅提供给会员学习使用!
7. 如遇到加密压缩包,请使用360解压,如遇到无法解压的请联系管理员
开心源码网 » Koa – Node.js框架学习@郝晨光