(一)初探
安装Koa 啥的我就不说了,看看官方例子
// 引入
const Koa = require('koa')
// 创建实例
const app = new Koa()
// 监听请求
app.use(async (ctx) => {
ctx.body = 'index Page'
})
// 绑定端口号
app.listen(3000, () => {
console.log('start running')
})
四步搞定~
不过我有了一个疑问,在 Koa 中 ctx 是啥?
代码:
{
"request": {
"method": "GET",
"url": "/",
"header": {
"host": "localhost:3000",
"connection": "keep-alive",
"cache-control": "max-age=0",
"upgrade-insecure-requests": "1",
"user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36",
"accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9",
"sec-fetch-site": "none",
"sec-fetch-mode": "navigate",
"sec-fetch-user": "?1",
"sec-fetch-dest": "document",
"accept-encoding": "gzip, deflate, br",
"accept-language": "zh-CN,zh;q=0.9,en;q=0.8",
"cookie": "_ga=GA1.1.1154242789.1594026649; dj_cityid=10177; dj_cityname=%E7%99%BD%E5%B1%B1; dj_location=126.427839%2C41.942505; dj_location_detail=%E5%96%9C%E4%B8%B0%E8%8A%B1%E5%9B%AD; dj_addr_id=1300259804379881472; comm_cityid=10177; comm_cityname=%u767D%u5C71"
}
},
"response": {
"status": 404,
"message": "Not Found",
"header": {}
},
"app": {
"subdomainOffset": 2,
"proxy": false,
"env": "development"
},
"originalUrl": "/",
"req": "<original node req>",
"res": "<original node res>",
"socket": "<original node socket>"
}
ctx 可见主要包括 response、request 两部分,可以理解为上(request)下(response)沟通的环境,所以koa中把他们两都封装进了ctx对象,koa官方文档里的解释是为了调用方便,ctx.req = ctx.request, ctx.res = ctx.response
body是http协议中的响应体,header是指响应头,ctx.body = ctx.res.body = ctx.response.body,ctx
.response.body
就是发送给用户的内容。
ctx.request 是 context经过封装的请求对象
ctx.req是context提供的node.js原生HTTP请求对象
ctx.response是context经过封装的响应对象
ctx.res是context提供的node.js原生HTTP请求对象
original node res:原生node
(二)处理 get 请求
// 引入
const Koa = require('koa')
// 创建实例
const app = new Koa()
// 监听请求
app.use(async (ctx) => {
ctx.body = {
url: ctx.url,
query: ctx.query,
queryString: ctx.querystring
}
})
// 绑定端口号
app.listen(3000, () => {
console.log('start running')
})
一般 get 请求 需要的就是 请求路径 以及 请求参数,ctx.query 是一个对象,一般直接 query
ctx.resquest = ctx 所以直接 ctx.xx 就可以,不需要 ctx.resquest.xxx
(三)使用 ejs 模版 以及 POST 中间件取参数
在 node 原生中,我们通过 fs.readFile 来读取文件内容,通过 res.end(data) 将文件数据展示到页面,在 koa 中 通过 koa-views 这个中间件,来展示页面
首先安装 ejs、koa-views
npm i koa-views ejs --save
代码:
const Koa = require('koa')
const views = require('koa-views')
const path = require('path')
const app = new Koa()
const bodyParser = require('koa-bodyparser')
// 加载模板引擎
app.use(views(path.join(__dirname, './views'), {
extension: 'ejs'
}))
// 引入 bodyParser 中间件
app.use(bodyParser())
app.use(async ( ctx ) => {
console.log(ctx.url) // /?name=zfb&aa=23
// ctx.url 带参数
// ctx.path 不带参数
if (ctx.path === '/' && ctx.method === 'GET') {
// views 文件目录下的 index.ejs
await ctx.render('index', {
pageData: JSON.stringify(ctx.query || {})
})
} else if (ctx.method === 'POST') {
// bodyParser中间件 将 post 请求的参数 放在 ctx.request.body 中
console.log(ctx.request.body)
ctx.body = ctx.request.body
}
})
app.listen(3000)
path.join(__dirname, './views') // /Users/macbook/Desktop/complier/views
ejs模版:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>index</title>
<!-- 写在head里 -->
<script type="text/javascript">
window.PAGE_DATA = <%-pageData%>
</script>
</head>
<body>
</body>
</html>
ejs:https://ejs.bootcss.com/#install
如果多个页面有公共的数据,比如三个页面的 pageData 都是一样的,可以把数据放到中间件中:
ctx.state 公共数据~
const Koa = require('koa')
const views = require('koa-views')
const path = require('path')
const app = new Koa()
const bodyParser = require('koa-bodyparser')
const Router = require('koa-router')
const router = new Router()
function getData () {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve({
name: 'zfb',
age: 23
})
}, 1000)
})
}
// 加载模板引擎
app.use(views(path.join(__dirname, 'views'), {
extension: 'ejs'
}))
// 引入 bodyParser 中间件
app.use(bodyParser())
// 中间件获取pagedata
// 把公共数据放入 ctx.state 中
app.use(async (ctx, next) => {
const result = await getData()
ctx.state = result
await next() // next 前要加await
})
router.get('/', async (ctx) => {
await ctx.render('index', {
pageData: ctx.state
})
})
router.get('/mine', async (ctx) => {
await ctx.render('mine', {
pageData: ctx.state
})
})
// 注册路由
app.use(router.routes())
app.listen(3000)