# -y 就是不想自己逐条配置,直接全部使用默认配置
npm init -y
# 安装 koa 并写入 package.json 中
npm i koa --save
# 好的代码规范还是必要的
npm i standard --save-dev
# 安装 nodemon 用于开发环境快速自动重启
npm i -g nodemon
这个时候我们就可以用到 npm script 了,避免重复输入命令
# package.json 中的 scripts 中添加
# 正常启动服务
"start": "node index.js",
# 启动开发环境,保存修改内容后自动重启
"dev": "NODE_ENV=develpment nodemon index.js"
这个时候我们新建一个文件叫 index.js 并编辑它
// index.js
// 引入 koa
const Koa = require('koa')
// 新建 koa 实例
const app = new Koa()
app.use(async (ctx) => { ctx.body = JSON.stringify(ctx) })
// 监听 5820 端口,服务启动成功输出内容
app.listen(5820, () => { console.log('APP LISTEN PORT 5820') })
然后我们在项目下打开终端,输入 npm run dev 就可以启动服务的开发模式了,这个时候可以看到控制台输出了 APP LISTEN PORT 5820,同时我们打开浏览器并访问 localhost:5820 ,就可以看到当前访问的上下文信息了
这是最简单的例子,同时也是最重要的,标志了你已可以正式启动 Koa 服务了
写一个最简单的例子
// 引入 koa
const Koa = require('koa')
// 新建 koa 实例
const app = new Koa()
app.use(async (ctx) => {
ctx.body = {
url: ctx.url,
params: ctx.request.query,
param_string: ctx.request.querystring,
ctx_params: ctx.query,
ctx_params_string: ctx.querystring
}
})
// 监听 5820 端口,服务启动成功输出内容
app.listen(5820, () => { console.log('APP LISTEN PORT 5820') })
这个时候,我们在浏览器提交一个请求,使用get访问 localhost:5820?hello=world&pika=qiu
这个时候我们就可以查看内容了
从这里可以看出
获取在 koa 中 GET 的参数方式有两种:query和querystring。同时我们可以看出,在可以从 request 中接收 GET 请求和直接从上下文中接收 GET 请求都是可以的。
koa 并不带 POST 请求的解析,这个时候,我们就要自己编写 POST 请求的解析函数了
function parseParams (ctx) {
return new Promise((resolve, reject) => {
try {
let paramsdata = ''
ctx.req.on('data', (data) => {
paramsdata += data
})
ctx.req.addListener('end', function () {
resolve(parseQueryStr(paramsdata))
})
} catch (error) {
reject(error)
}
})
}
function parseQueryStr (queryStr) {
let queryData = {}
let queryStrList = queryStr.split('&')
for (let [index, queryStr] of queryStrList.entries()) {
let itemList = queryStr.split('=')
queryData[itemList[0]] = decodeURIComponent(itemList[1])
}
return queryData
}
使用的时候就可以这么使用
app.use(async (ctx) => {
let params = await parseParams(ctx)
ctx.body = {
method: ctx.method,
url: ctx.url,
params
}
})
这个时候,我们可以使用 POSTMAN 来模拟一下 POST 请求的发送,我们可以发现参数已经被成功解析了
当然 POST 请求这么常见的需求是一定有造好的轮子的,这个时候我们就可以使用 koa-bodyparser 来进行参数的解析了
npm i koa-bodyparser --save
// 引入 koa
const Koa = require('koa')
// 引入 koa-bodyparser
const KoaBodyparser = require('koa-bodyparser')
// 新建 koa 实例
const app = new Koa()
// 使用中间件
app.use(KoaBodyparser())
app.use(async (ctx) => {
ctx.body = {
method: ctx.method,
url: ctx.url,
params: ctx.request.body
}
})
// 监听 5820 端口,服务启动成功输出内容
app.listen(5820, () => { console.log('APP LISTEN PORT 5820') })
然后我们使用 POSTMAN 模拟一下请求就可以看出,这里我们直接使用 ctx.request.body 就可以取到格式化后的参数对象了
先编写一个简单的中间件
// 因为使用了 fs 模块,所以我们要引入
const fs = require('fs')
// 先写好对应的文件,然后写一个读取文件内容的函数
function readfile (params) {
return new Promise((resolve, reject) => {
fs.readFile(`./route/${params}.html`, 'binary', (err, data) => {
if (err) {
reject(err)
} else {
resolve(data)
}
})
})
}
// 再编写路由配置
async function route (url) {
let page = ''
switch (url) {
case '/index':
page = 'index'
break
case '/page':
page = 'page'
break
case '/user':
page = 'user'
break
default: page = '/404'
break
}
let html = await readfile(page)
return html
}
// 就可以这么使用了
app.use(async (ctx) => {
let html = await route(ctx.url)
ctx.body = html
})
当然,常用的东西肯定是有中间件的,这个时候我们就可以祭出 koa-router
npm i koa-router --save
// 引入 koa
const Koa = require('koa')
// 引入 koa-router
const KoaRouter = require('koa-router')
// 实例化一个 koa 对象
const app = new Koa()
// 实例化一个 router 对象
let route = new KoaRouter()
// 表示接收 get 请求,接收 url 为 /
// 其中 next 指的是下一个中间件,可以在代码中使用 await next() 来提前执行
route.get('/', (ctx, next) => {
ctx.body = 'Hello get'
})
// 表示接收 post 请求
route.post('/test', (ctx, next) => {
ctx.body = 'hello post'
})
// 表示接收全部请求
route.all('/all', (ctx, next) => {
ctx.body = 'hello all'
})
// 装载路由,并只允许指定方法访问
app.use(route.routes()).use(route.allowedMethods())
// 监听 5820 端口,服务启动成功输出内容
app.listen(5820, () => { console.log('APP LISTEN PORT 5820') })
当然,日常工作中的路由不可能这么简单,这个时候我们就需要使用多层次的路由的,下面看案例
先简单创建一下目录并路由文件
mkdir route
touch route1.js route2.js
// route1.js
let KoaRouter = require('koa-router')
let route = new KoaRouter()
route.get('/test1', (ctx, next) => {
ctx.body = 'route1 test1'
})
route.get('/test2', (ctx, next) => {
ctx.body = 'route1 test2'
})
route.get('/test3', (ctx, next) => {
ctx.body = 'route1 test3'
})
module.exports = route
// route2.js
let KoaRouter = require('koa-router')
let route = new KoaRouter()
route.get('/test1', (ctx, next) => {
ctx.body = 'route2 test1'
})
route.get('/test2', (ctx, next) => {
ctx.body = 'route2 test2'
})
route.get('/test3', (ctx, next) => {
ctx.body = 'route2 test3'
})
module.exports = route
// 根目录下的 server.js
// 引入 koa,路由
const Koa = require('koa')
let KoaRouter = require('koa-router')
// 实例化一个 koa 对象
const app = new Koa()
// 创建一个全局的父路由,子路由要全部挂载在父路由下
let fatherRoute = new KoaRouter()
// 引入子路由
const route1 = require('./route/route1')
const route2 = require('./route/route2')
// 装载路由,并只允许指定方法访问
fatherRoute.use('/route1', route1.routes(), route1.allowedMethods())
fatherRoute.use('/route2', route2.routes(), route2.allowedMethods())
// Koa 装载父路由
app.use(fatherRoute.routes()).use(fatherRoute.allowedMethods())
// 监听 5820 端口,服务启动成功输出内容
app.listen(5820, () => { console.log('APP LISTEN PORT 5820') })
这个时候我们就可以启动,然后访问 localhost:5820/route1/test1
localhost:5820/route2/test3 来查看一下效果
// 引入 koa
const Koa = require('koa')
// 引入 koa-router
const KoaRouter = require('koa-router')
// 实例化一个 koa 对象
const app = new Koa()
// 实例化一个 router 对象
let route = new KoaRouter()
// 最简单的 key-value 形式,可以直接使用上下文对象提供的 cookie 对象进行操作
route.get('/', (ctx, next) => {
ctx.cookies.set(
'TESTCOOKIE', 'LOVEWZJ'.repeat(5)
)
ctx.body = 'SET COOKIE OK'
})
// 获取 cookie
route.get('/test', (ctx, next) => {
ctx.body = `GET COOKIE IS ${ctx.cookies.get('TESTCOOKIE')}`
})
// 装载路由,并只允许指定方法访问
app.use(route.routes()).use(route.allowedMethods())
// 监听 5820 端口,服务启动成功输出内容
app.listen(5820, () => { console.log('APP LISTEN PORT 5820') })
// 复杂的 key-value-options 形式
route.get('/', (ctx, next) => {
ctx.cookies.set(
'TESTCOOKIE', 'LOVEWZJ', {
maxAge: 1000 * 60 * 60 * 24,
expires: new Date('2018-12-31')
}
)
ctx.body = `SET COOKIE OK ${new Date().toLocaleTimeString()}`
})
名称 | 含义 | 示例 |
---|---|---|
path | cookie 的路径 | 默认 / |
domain | cookie 的域 | *.baidu.com |
expires | cookie 有效期时间 | new Date(‘2018-12-31’) |
maxAge | cookie 最大存活时间 | 1000 * 60 * 60 * 24 |
httpOnly | 是否只能通过 HTTP 协议发送 | true|false |
signed | 是否要做签名 | true|false |
secure | 通过什么协议发送 cookie | false 表示 cookie 通过 HTTP 协议发送,true 表示 cookie 通过 HTTPS 发送 |
overwirte | 是否允许重写 | true|false |
对于一些静态的资源,比如图片,CSS文件,JS文件,HTML文件等资源,我们可以直接使用 koa-static 中间件进行处理。
npm i kao-static --save
注意:这里是把所有的静态资源放在 static 目录下
// 引入 koa
const Koa = require('koa')
// 引入 path 模块
const path = require('path')
// 引入 koa-static 中间件
const KoaStatic = require('koa-static')
// 实例化一个 koa 对象
const app = new Koa()
// 装载静态资源中间件
app.use(KoaStatic(
path.join(__dirname, './static')
))
// 监听 5820 端口,服务启动成功输出内容
app.listen(5820, () => { console.log('APP LISTEN PORT 5820') })
app.use() 的功能实际上就是把里面的函数加入到回调函数执行列表中,下面我们写一个简单的例子来看一下
// 引入 koa
const Koa = require('koa')
// 实例化一个 koa
const app = new Koa()
app.use(log)
app.use(async (ctx) => { ctx.body = ctx.url })
// 我们写的异步程序
async function log (ctx, next) {
ctx.url = 'I CAN CHANGE CTX URL'
await next()
}
// 监听 5820 端口,服务启动成功输出内容
app.listen(5820, () => { console.log('APP LISTEN PORT 5820') })