Koa2

koa2官网: https://koa.bootcss.com/

一. 安装koa2

Koa 依赖 node v7.6.0 或 ES2015及更高版本和 async 方法支持.

cnpm i koa --save

二. hello world

const Koa = require('koa')//引入Koa

const app = new Koa();   //实例化Koa

app.use(async (ctx) => {    //使用app
    ctx.body = 'hola'       //ctx就是context上下文,是Koa自带的对象
})
app.listen(3000);
context是什么?

我们先查看下ctx对象

Koa Context将节点的请求和响应对象封装到单个对象中,该对象为编写Web应用程序和API提供了许多有用的方法。
简单来说:

  • ctx.url 是Koa请求的路径
  • ctx.request是Koa请求对象;
  • ctx.response 是Koa响应对象
  • ctx.body body是http协议中的响应体 ctx.body = ctx.res.body = ctx.response.body
  • ctx.req 是原生nodejs.request请求对象
  • ctx.res 是原生nodejs.response响应对象
  • ctx.method 是Koa的请求方法
    想了解上下文context,请看文章:https://www.jianshu.com/p/9488cd3feaf9

三. 接收get请求接收

Koa接收的get请求会存入上下文中,我们只需要从上下文中通过ctx.request取出即可

const Koa = require("koa")

const app = new Koa();
app.use(
    async (ctx) => {
        let url = ctx.url;
        let request = ctx.request;
        let req_query = req.query;
        let req_querystring = req.querystring;

        ctx.body = {
            url,
            req_query,
            req_querystring
        }
    }
)
app.listen(
    3000, () => {
        console.log('running');
    }
)

其中ctx.request.query是请求中的query对象,


其中 ctx.request.querystring是请求中的query字符串,

除了使用 ctx.request.queryctx.request.querystring之外,问了方便使用,koa还允许用 ctx.query ctx.querystring这样的简写

四. Post请求接收

对于POST请求的处理,Koa2没有封装方便的获取参数的方法,需要通过解析上下文context中的原生node.js请求对象req来获取。

1. 原生方法获取Post请求的步骤:(仅为了学习原理)

  • 解析上下文ctx中的原生nodex.js对象req。
  • 将POST表单数据解析成query string-字符串.(例如:user=jspang&age=18)
  • 将字符串转换成JSON格式。
const Koa = require("koa")

const app = new Koa();
app.use(
    async (ctx) => {
        if (ctx.url === '/' && ctx.method === "GET") {
            ctx.body = `    <h1>haha</h1>
            <form action="/" method="post">
                <input type="text" name="name">
                <input type="number" name="age">
                <button type="submit">OK</button>
            </form>`
        } else if (ctx.url === '/' && ctx.method === "POST") {
            let postdata = await parsePost(ctx)  //注意是异步调用
            ctx.body = postdata
        } else {
            ctx.body = '404'
        }
    }
)
function parsePost(ctx) { //解析ctx里的post
    return new Promise((resolve, reject) => {
        try {
            let postdata = '';
            ctx.req.addListener('data', (data) => {  //ctx.req添加监听事件监听data的变化
                postdata = data.toString(); //接收新的data并转为字符串
                parseQueryStr(postdata);//将字符串转为JSON对象
            })
            ctx.req.on('end', function () {  //ctx.req添加监听事件监听end
                resolve(parseQueryStr(postdata))
            })
        } catch (error) {
            reject(error)
        }
    })
}
function parseQueryStr(queryStr) {//此函数用于将Post字符串转化为对象
    let queryData = {}
    let queryStrList = queryStr.split('&')
    for (let [index, queryStrInList] of queryStrList.entries()) {
        let itemList = queryStrInList.split('=')
        queryData[itemList[0]] = decodeURIComponent(itemList[1])
    }
    return queryData
}
app.listen(
    3000, () => {
        console.log('running');
    }
)

2. 使用中间件 koa-bodyparser

(1).安装
cnpm i koa-bodyparser --save
(2). 使用
//引入
const bodyparser=require('koa-bodyparser')
//使用
app.use(bodyparser())

经过上面的步骤后,当有post请求时,koa-bodyparser会自动将解析好的对象放入 ctx.request.body之中
上面的程序可以改成:

const Koa = require("koa")
const bodyparser = require('koa-bodyparser')
const app = new Koa();

app.use(bodyparser())
app.use(
    async (ctx) => {
        if (ctx.url === '/' && ctx.method === "GET") {
            ctx.body = `    <h1>haha</h1>
            <form action="/" method="post">
                <input type="text" name="name">
                <input type="number" name="age">
                <button type="submit">OK</button>
            </form>`
        } else if (ctx.url === '/' && ctx.method === "POST") {
            let postdata = ctx.request.body  //注意是异步调用
            ctx.body = postdata
        } else {
            ctx.body = '404'
        }
    }
)
app.listen(
    3000, () => {
        console.log('running');
    }
)

五. 路由

1. 原生路由 (仅为了学习原理)

const Koa = require("koa")
const fs = require('fs')
const app = new Koa();
app.use(
    async (ctx) => {
        let html = await myrouter(ctx.url);
        ctx.body = html
    }
)
async function myrouter(url) {
    let page = '404.html'
    switch (url) {
        case '/':
            page = 'index.html'
            break;
        case '/index':
            page = 'index.html'
            break;
        case '/todo':
            page = 'todo.html'
            break;
        default:
            break;
    }
    let html = await myrender(page);
    return html
}
async function myrender(page) {
    return new Promise((resolve, reject) => {
        fs.readFile(`./page/${page}`, 'binary', (err, data) => {
            if (err) reject(err);
            resolve(data);
        })
    })
}
app.listen(
    3000, () => {
        console.log('running');
    }
)

2. 使用中间件 koa-router

cnpm install koa-router --save
(1). 基本使用方法
//1. 引入
const Router = require('koa-router')

//2. 实例化
const router = new Router();

//3. 写请求处理
router.get('/', (ctx, next) => {
    ctx.body='hola'
})

//4. app用起来
app.use(router.routes())

例:

const Koa = require("koa")
const fs = require('fs')
const Router = require('koa-router')

const app = new Koa();
const router = new Router();

router
    .get('/', (ctx, next) => {
        ctx.body = 'hola'
    })
    .get('/todo', (ctx, next) => {
        ctx.body = 'todos'
    })

app
    .use(router.routes())
    .use(router.allowedMethods())

app.listen(
    3000, () => {
        console.log('running');
    }
)

我们把原生的例子改为用koa-router

const Koa = require("koa")
const fs = require('fs')
const Router = require('koa-router')

const app = new Koa();
const router = new Router();

router
    .get('/', async (ctx, next) => {
        ctx.body = await getPage('index')
    })
    .get(['/todo', '/index'], async (ctx, next) => {
        ctx.body = await getPage(ctx.url)
    })
    .get('*', async (ctx, next) => {
        ctx.body = await getPage(404)
    })
async function getPage(url) {
    return new Promise((resolve, reject) => {
        fs.readFile(`./page/${url}.html`, 'binary', (err, data) => {
            if (err) reject(err)
            console.log(data);
            resolve(data)
        })
    })
}
app
    .use(router.routes())
    .use(router.allowedMethods())

app.listen(
    3000, () => {
        console.log('running');
    }
)
(2). 路由的层级
①. 前缀

给路由直接增加一个层级

const router = new Router({
    prefix:'/hola'
});

这样一来, 原先 /xxx访问的页面 要/hola/xxx 来访问了~~

③. 主路由子路由分离
  • 分别实例化父路由及子路由
  • 配置子路由
  • 父路由挂载子路由
const Koa = require("koa")
const Router = require('koa-router')

const app = new Koa();
const router = new Router(); //父路由
const home = new Router();   //子路由
const page = new Router();   //子路由

home
    .get('/', async (ctx, next) => {
        ctx.body = '/home/index'
    })
    .get('/todo', async (ctx, next) => {
        ctx.body = '/home/todo'
    })
page
    .get('/', async (ctx, next) => {
        ctx.body = '/page/index'
    })
    .get('/todo', async (ctx, next) => {
        ctx.body = '/page/todo'
    })

router.use('/home', home.routes(), home.allowedMethods())
router.use('/page', page.routes(), page.allowedMethods())

app
    .use(router.routes())
    .use(router.allowedMethods())
app.listen(
    3000, () => {
        console.log('running');
    }
)

六. cookie

cookie也被封装进了ctx
cookie的读: ctx.cookies.get('键')
cookie的写: ctx.cookies.set('键','值',{配置})

const Koa = require("koa")

const app = new Koa();

app.use(
    async (ctx) => {
        if (ctx.url === '/index') {
            ctx.cookies.set(
                'MyName', 'lili', {   //cookie的键值
                domain: ['127.0.0.1'],  //cookie的域名信息
                maxAge: 1000 * 60 * 60 * 24 * 10, //最大有效事件 单位毫秒
                expires: new Date('2020-05-01'),  //失效时间
                httpOnly: false,  //只允许http请求时才有效,一般填false
                overwrite: false   //允许重写?  一般填false
            }
            )
            ctx.body = 'Cookie is Ok'
        } else {
            if (ctx.cookies.get('MyName')) {
                ctx.body = ctx.cookies.get('MyName')
            } else {
                ctx.body = 'cookie is not ready'
            }
        }
    }
)
app.listen(
    3000, () => {
        console.log('running');
    }
)

七. 模板引擎 koa-views ejs

cnpm i koa-views --save
cnpm i ejs --save
const Koa = require("koa")
const views = require('koa-views')
const path = require('path')

const app = new Koa();

app.use(views(path.join(__dirname, './view'), {
    extension: 'ejs'
}))

app.use(
    async (ctx) => {
        await ctx.render('index', {
            title: 'hola~你好啊!'
        })
    }
)
app.listen(
    3000, () => {
        console.log('running');
    }
)

八. 引用静态资源

cnpm i koa-static --save
  • 引入中间件
  • 设置好公开的静态资源目录
  • app用起来
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('running');
    }
)
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值