Koa学习笔记
- 前后端常见的几种鉴权方式:https://blog.csdn.net/wang839305939/article/details/78713124
- Koa鉴权设定:https://segmentfault.com/a/1190000011557953
Koa
Koa简介
- 概述:Koa是一个新的 web框架,致力于成为 web应用 和 API开发 领域中的一个更小、更富有表现力、更健壮的基石。
- 特点:
* 轻量、无捆绑
* 中间件架构
* 优雅的 API 设计
* 增强的错误处理
试用
- 安装:npm i koa -S
中间件机制、请求、响应处理
- 中间件机制——洋葱模型
- 代码
const Koa = require('koa')
const app = new Koa()
// 中间件框架
// 中间件是一个异步函数,对用户请求和响应做预处理
app.use(async (ctx, next) => {
// next上面:请求操作
await next() // 分界线
// next下面:响应操作
// 获取响应头,印证执行顺序
const rt = ctx.response.get('X-Response-Time')
console.log(`输出计时:${
ctx.method} ${
ctx.url} - ${
rt}`)
})
// 响应时间统计中间件
app.use(async (ctx, next) => {
const start = Date.now()
console.log('开始计时')
await next()
const ms = Date.now() - start
ctx.set('X-Response-Time', `${
ms}ms`)
console.log('计时结束')
})
// 响应用户请求
app.use(ctx => {
console.log('响应用户请求')
// 设置响应状态码
ctx.status = 200
// 设置响应类型,等效于 ctx.set('Content-Type', 'text/html')
ctx.type = 'html'
// 设置响应体
ctx.body = '<h1>Hello Koa</h1>'
})
// 开始监听端口,等同于 http.createServer(app.callback()).listen(3000)
app.listen(3000)
- 测试访问 http://localhost:3000,后台结果输出:
开始计时
响应用户请求
计时结束
输出计时:GET / - 5ms
错误处理
const Koa = require('koa')
const app = new Koa()
// 错误处理中间件(写在最上面)
app.use(async (ctx, next) => {
try {
await next()
} catch (error) {
// 响应用户
ctx.status = error.statusCode || error.status || 500
// 给用户响应信息
ctx.body = error.message
// 触发应用层级错误事件
ctx.app.emit('error', error, ctx)
console.log('捕获到错误:', error.message)
}
})
// 响应时间统计中间件
// ...
// 触发错误
app.use(async (ctx, next) => {
// throw new Error('未知错误')
ctx.throw(401, '认证失败')
})
// 响应用户请求
//...
// 全局错误事件(写在最后面,不是必须)
app.on('error', err => {
console.error('全局错误处理:', err.message)
})
// 开始监听端口,等同于 http.createServer(app.callback()).listen(3000)
app.listen(3000)
路由
- 安装:npm i -S koa-router
- 路由分模块编写:
// ./routes/index.js
const Router = require('koa-router')
const router = new Router()
router.get('/', ctx => {
ctx.body = 'index'
})
module.exports = router
// ./routes/users.js
const Router = require('koa-router')
const router = new Router({
prefix: '/users'})
router.get('/', ctx => {
ctx.body = 'users list'
})
module.exports = router
// ./app.js
// ... 其他中间件
// 导入路由文件
const index = require('./routes/index')
const users = require('./routes/users')
// 写在通用中间件的后面
app.use(index.routes())
app.use(users.routes())
- 访问测试:http://localhost:3000、http://localhost:3000/users
静态文件服务
- 安装:npm i -S koa-static
- 使用:
// 返回静态文件服务中间件应该放在错误处理之后,用户请求处理之前
const static = require('koa-static')
app.use(static(__dirname + '/public'))
- 访问测试:http://localhost:3000/hello.html
模板引擎
- 安装:npm i -S koa-hbs@next
基本使用
- 引入并配置,app.js:
// 引入模板引擎
const hbs = require('koa-hbs')
app.use(hbs.middleware({
// 视图根目录
viewPath: __dirname + '/views',
// 默认布局页面
defaultLayout: 'layout',
// 注册 partial 目录(可复用的页面)
partialsPath: __dirname + '/views/partials',
// 开发阶段不缓存
disableCache: true
}))
- 创建目录 views、views/partials,创建文件layout.hbs、index.hbs
- layout.hbs:
<!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>{
{
title}}</title>
</head>
<body>
{
{!-- 页头 --}}
页头
{
{
{
body}}}
{
{!-- 页脚 --}}
页脚
</body>
</html>
- index.js:传值
router.get('/',async ctx => {
// ctx.body = 'index'
// 渲染页面 => views 目录下的index.hbs页面
await ctx.render('index', {
title: '用户列表',
subTitle: 'handlerbars语法',
htmlStr: '<div style="color: red;">handlerbars HTML 替换</div>',
isShow: true,
username: 'yw',
users: [
{
username: 'tom', age: 20},
{
username: 'jerry', age: 24}
]
})
})
- index.hbs:显示
{
{!-- 1. 插值绑定 --}}
<h1>{
{
subTitle}}</h1>
{
{!-- 2. 注释 --}}
{
{!-- 3. HTML内容 --}}
<p>{
{
{
htmlStr}}}</p>
{
{!-- 4. 条件语句 --}}
{
{
#if isShow}}
<p>{
{
username}},欢迎你!</p>
{
{
else}}
<a href="#">请登录</a>
{
{
/if}}
{
{!-- 5. 循环 --}}
<ul>
{
{
#each users}}
<li>{
{
username}} - {
{
age}}</li>
{
{
/each}}
</ul>
- 访问测试:http://localhost:3000/
部分视图
——提取通用内容至独立文件
- 创建 ./views/partials/nav.hbs
- 引用:./views/layout.hbs
{
{
>nav}}
帮助方法
——扩展 handlebars 的功能函数
- 创建 ./utils/helpers.js
const hbs = require('koa-hbs')
const moment = require('moment')
// 日期格式化方法
hbs.<