搭建koa开发环境
koa基于async,需要node版本7.6以上
- 新建一个文件夹并进入
- 生成package.json文件
- 安装koa(–save安装到生产环境)
- 新建一个文件index.js
1 2 3 4 5 6 7 8
| const Koa = require('koa') const app = new Koa()
app.use(async(ctx)=>{ ctx.body = 'hello,leni' }) app.listen(3000) console.log('app is starting at port 3000')
|
终端执行
就可以在浏览器输入127.0.0.1:3000访问了。
async和await的使用
- 新建一个文件demo01.js, 普通函数加上async就变成异步的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| function getSth(){ return 'something' }
async function testAsync(){ return 'hello,async' }
async function test(){ const v1 = await getSth() const v2 = await testAsync() console.log(v1,v2) }
test()
const result = testAsync() console.log(result)
|
await会造成阻塞,所以必须放在异步方法里面,不然程序可能会崩溃
所以await两个特点
- 必须放在异步方法里面
- 不仅能接收异步的,普通函数返回的结果也可以
get请求数据的接收
新建一个文件demo02.js
在koa2中get请求通过request接收,但是接收的方法有两种:query和querystring
- query:返回的是格式化好的参数对象
- querystring:返回的是请求字符串
koa也可以不用request接收请求, 见demo
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| const Koa = require('koa') const app = new Koa() app.use(async(ctx)=>{ let url = ctx.url let request = ctx.request let req_query = request.query let re_querystring = request.querystring let ctx_query = ctx.query let ctx_querystring = ctx.querystring ctx.body = { url, req_query, req_querystring, ctx_query, ctx_querystring } }) app.listen(3000,()=>{ console.log('[demo] is starting at port 3000') })
|
访问127.0.0.1:3000带参数
127.0.0.1:3000?name=leni&age=18
(可以安装iformattool插件)
Post请求如何接收
针对post请求,koa没有封装方便的获取参数的方法,需要通过解析上下文context中原生node.js请求对象req来获取。
获取Post请求的步骤:
- 解析上下文ctx中的原生node.js的req
- 将Post表单数据解析成query string字符串
- 将字符串转换为JSON格式
ctx.request和ctx.req的区别
- ctx.request:是koa2中contex经过封装的请求对象,用起来比较直观简单
- ctx.req:是context提供的node.js原生Http请求对象。不直观,有更多的内容,但是适合深度编程
新建一个文件demo03.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| const Koa = require('koa') const app = new Koa()
app.use(async(ctx)=>{ if(ctx.url === '/' && ctx.method === 'GET'){ let html = ` <h1>leni Koa2 request Post</h1> <form method='POST' action='/'> <p>userName</p> <input name='userName'/><br/> <p>age</p> <input name='age'/><br/> <button type='submit'>submit</button> </form> ` ctx.body = html }else if(ctx.url === '/' && ctx.method === 'POST'){ ctx.body = '接收到post参数' }else{ ctx.body = '<h1>404</h1>' } })
app.listen(3000,()=>{ console.log('[demo03] is starting at port 3000') })
|
解析node原生post参数
用promise对象进行解析,使用ctx.req.on来接收事件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| function parsePostData(ctx){ return new Promise((resolve,reject)=>{ try { let postData = '' ctx.req.on('data',data=>{ postData += data }) ctx.req.addListener('end', function(){ resolve(postData) }) } catch (error) { reject(error) } }) }
|
然后在接收post请求的处理方法里,修改代码:
1 2
| let postData = await parsePostData(ctx) ctx.body = postData
|
POST字符串解析为JSON对象
写一个字符串封装成JSON对象的方法
1 2 3 4 5 6 7 8 9
| function parseQueryStr(queryStr){ let queryData = {} let queryStrList = queryStr.split('&') for(let item of queryStrList){ let itemList = item.split('=') console.log(itemList) queryData[itemList[0]] = decodeURIComponent(itemList[1]) } }
|
Koa-bodyparser中间件
安装
1
| npm i --save koa-bodyparser@3
|
新建一个文件demo04.js,复用上一个demo代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| const Koa = require('koa') const app = new Koa() const bodyparser = require('koa-bodyparser')
app.use(bodyparser())
app.use(async(ctx)=>{ if(ctx.url === '/' && ctx.method === 'GET'){ let html = ` <h1>leni Koa2 request Post</h1> <form method='POST' action='/'> <p>userName</p> <input name='userName'/><br/> <p>age</p> <input name='age'/><br/> <button type='submit'>submit</button> </form> ` ctx.body = html }else if(ctx.url === '/' && ctx.method === 'POST'){ let postData = ctx.request.body ctx.body = postData }else{ ctx.body = '<h1>404</h1>' } })
app.listen(3000,()=>{ console.log('[demo03] is starting at port 3000') })
|
koa2原生路由实现
新建一个文件demo05.js, 新建一个文件夹page(放404.html,index.html,todo.html)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
| const Koa = require('koa') const app = new Koa() const fs = require('fs')
function render(page){ return new Promise((resolve,reject)=>{ let pageUrl = `./page/${page}` fs.readFile(pageUrl, 'binary', (err, data)=>{ if(err){ reject(err) }else{ resolve(data) } }) }) }
async function route(url){ let page = '404.html' switch(url){ case '/': page = 'index.html' break; case '/index': page = 'index.html' break; case '/todo': page = 'todo.html' break; case '/404': page = '404.html' break; default: break; } let html =await render(page) return html; }
app.use(async(ctx)=>{ let url = ctx.request.url let html =await route(url) ctx.body = html })
app.listen(3000)
|
index.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <h1>Koa demo Index Page</h1> <p>this is Index page</p> <ul> <li><a href="/">/</a></li> <li><a href="/index">index</a></li> <li><a href="/todo">todo</a></li> <li><a href="/404">404</a></li> </ul> </body> </html>
|
todo.html
1 2 3 4 5 6 7 8 9 10 11 12
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <h1>Koa demo Todo Page</h1> <p>this is todo page</p> </body> </html>
|
404.html
1 2 3 4 5 6 7 8 9 10 11 12
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <h1>Koa demo 404 Page</h1> <p>this is 404 page</p> </body> </html>
|
Koa-router中间件(1)
安装
新建文件demo06.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| const Koa = require('koa') const Router = require('koa-router') const app = new Koa() const router = new Router() router .get('/', (ctx, next)=>{ ctx.body = 'index page' }) .get('/todo', (ctx, next)=>{ ctx.body = 'todo page' }) app.use(router.routes()).use(router.allowedMethods()) app.listen(3000,()=>{ console.log('[demo06] is starting at port 3000') })
|
Koa-router中间件 (2) 层级
新建文件demo07.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| const Koa = require('koa') const Router = require('koa-router') const app = new Koa()
let home = new Router() home.get('/leni', async(ctx)=>{ ctx.body = 'Home leni page' }).get('/todo', async(ctx)=>{ ctx.body = 'Home todo page' })
let page = new Router() page.get('/leni', async(ctx)=>{ ctx.body = 'Page leni page' }).get('/todo', async(ctx)=>{ ctx.body = 'Page todo page' })
const router = new Router() router.use('/home', home.routes(), home.allowedMethods()) .use('/page', page.routes(), page.allowedMethods())
app.use(router.routes()).use(router.allowedMethods()) app.listen(3000,()=>{ console.log('[demo07] is starting at port 3000') })
|
Koa-router中间件 (3) 参数
新建文件demo08.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| const Koa = require('koa') const Router = require('koa-router')
const app = new Koa() const router = new Router()
router.get('/', (ctx,next)=>{ ctx.body = ctx.query })
app.use(router.routes()).use(router.allowedMethods())
app.listen(3000,()=>{ console.log('[demo08] is starting at port 3000') })
|
cookie的使用
新建文件demo09.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| const Koa = require('koa') const app = new Koa() app.use(async(ctx)=>{ if(ctx.url === '/index'){ ctx.cookies.set( 'MyName', 'Leni', { domain: '127.0.0.1', path: '/', maxAge: 1000*60*60*24, expires: new Date('2020-03-01'), httpOnly: false, overwirte: false } ) ctx.body = 'Cookie is ok' }else{ if(ctx.cookies.get('MyName')){ ctx.body = ctx.cookies.get('MyName') }else{ ctx.body = 'hello, leni' } } }) app.listen(3000,()=>{ console.log('[demo09] is starting at port 3000') })
|
ejs模板
安装中间件
安装ejs模板引擎
编写模板,为了模板同一管理,新建文件夹view(含index.ejs)
views/index.ejs
1 2 3 4 5 6 7 8 9 10
| <!DOCTYPE html> <html> <head> <title><%= title %></title> </head> <body> <h1><%= title %></h1> <p>EJS Welcome to <%= title %></p> </body> </html>
|
新建文件demo10.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| const Koa = require('koa') const app = new Koa() const path = require('path') const views = require('koa-views') app.use(views(path.join(__dirname,'./views'),{ extension: 'ejs' })) app.use(async(ctx)=>{ let title = 'hello, koa2' await ctx.render('index', { title }) }) app.listen(3000,()=>{ console.log('[dmeo10] is starting at port 3000') })
|
koa-static静态资源中间件
安装koa-static
新建static文件夹,放入静态资源
新建文件demo11.js
1 2 3 4 5 6 7 8 9 10 11 12
| const Koa = require('koa') const path = require('path') const static = require('koa-static') const app = new Koa() const staticPath = './static' app.use(static(path.join(__dirname,staticPath))) app.use(async(ctx)=>{ ctx.body = 'hello, world' }) app.listen(3000, ()=>{ console.log('[dmeo11] is starting at port 3000') })
|
访问127.0.0.1:3000/index.js(资源文件名)就可以访问静态资源了
补充
app.use(function): 将给定的中间件方法添加到此应用程序中。
demo地址:https://github.com/leniNikky/koa-simple-demo