黑马程序员技术交流社区

标题: 【上海校区】聊聊 koa 中间件 [打印本页]

作者: 不二晨    时间: 2018-8-3 10:38
标题: 【上海校区】聊聊 koa 中间件
前言koa是基于Node.js平台的下一代web开发框架,它体积小,扩展性强,给人一种干净利落的编程方式,且由express原班人马打造,国内很多互联网公司都在使用,因此有必要学习总结下。
初出茅庐,来个hello wordlet Koa = require('koa'); //引入koalet app = new Koa();    //声明一个实例appapp.use(async (ctx,next)=>{   //  对于任何请求,app将调用该异步函数处理请求:    ctx.body = "hello"});app.listen("3000");  //监听端口复制代码

简捷的5行代码,帮我们开启了3000端口的服务
深入理解Koa中间件之洋葱模型学习Koa重点在于理解中间件实现原理,对后续引用第三方库中间件时候有更好了解。我们单独讲讲
let Koa = require('koa');let app = new Koa();app.use(async (ctx,next)=>{    console.log(1);   await next();    console.log(2);});app.use(async (ctx,next)=>{    console.log(3);   await next();    console.log(4);});app.listen("3000");复制代码
你可能对运行的结果会说 1234,其实不然,我们先来看下输出结果




一脸懵逼1342,这是什么顺序,这就是我们要说的洋葱模型


1、koa-router中间件koa-router基础写法let Koa = require('koa');let app = new Koa();let Router = require('koa-router');let router = new Router();router.get('/',async (ctx,next)=>{    ctx.body = 'hello people';    await next()});router.get('/list',async (ctx,next)=>{    ctx.body = 'list';});app.use(router.routes()); // 挂载app.use(router.allowedMethods());//当请求数据的方法与设置的方法不一致,会报错。比如默认get请求获取,用post发请求会报错app.listen(3000);复制代码koa-router中嵌套路由写法
假如我们想为单个页面设置层级,/home是我们首页,再次基础上有/home/list 首页列表页 /home/todo 首页todo页。这时我们就需要用到嵌套路由,看看怎么用
const Koa = require('koa');const app = new Koa();const Router = require('koa-router');//home的路由let home = new Router();home.get('/list',async(ctx)=>{    ctx.body="Home list";}).get('/todo',async(ctx)=>{    ctx.body ='Home ToDo';});//page的路由let page = new Router();page.get('/list',async(ctx)=>{    ctx.body="Page list";}).get('/todo',async(ctx)=>{    ctx.body ='Page todo';});//装载所有子路由let router = new Router();router.use('/home',home.routes(),home.allowedMethods());router.use('/page',page.routes(),page.allowedMethods());//加载路由中间件app.use(router.routes()).use(router.allowedMethods());app.listen(3000);复制代码
这样一来就实现嵌套路由的写法


koa-router参数的传递let Koa = require('koa');let app = new Koa();let Router = require('koa-router');let router = new Router();//实现  /arcicle/id/name形式的传参router.get('/acticle/:id/:name',(ctx,next)=>{    ctx.body = ctx.params.id +"-"+ ctx.params.name;});app.use(router.routes());app.listen(3000);复制代码
测试下,学过vue应该比较熟悉

const Koa = require('koa');const Router = require('koa-router');const app = new Koa();const router = new Router();router.get('/article', function (ctx, next) {    ctx.body=ctx.query; //query方法实现json形式});app.use(router.routes())app.listen(3000,()=>{    console.log('starting at port 3000');});复制代码

2、koa-bodyparse()中间件let Koa = require('koa');let bodyParser = require('koa-bod')let app = new Koa();app.use(bodyParser()); // 解析请求体的中间件app.use(async (ctx, next) => {    if (ctx.path === '/' && ctx.method === 'GET') {        ctx.set('Content-Type', 'text/html;charset=utf8');        ctx.body = `        <form action="/" method="post">            <input type="text" name="username" >            <input type="text" name="password" >            <input type="submit" >        </form>        `    }});app.use(async (ctx, next) => {    if (ctx.method === 'POST' && ctx.path === '/') {        // 获取表单提交过来的数据        ctx.body = ctx.request.body;    }});app.listen(3000);复制代码
当post提交表单获得表单数据,测试下结果


3、koa-better-body中间件
来个demo体验下,我们把本地的1.txt文件上传到upload文件夹中。 1.txt内容为123456789
let Koa = require('koa');let app = new Koa();let betterBody = require('koa-better-body'); // v1插件 let convert = require('koa-convert'); // 将1.0的中间件 转化成2.0中间件app.use(convert(betterBody({    uploadDir: __dirname //指定上传的目录 __dirname当前文件夹绝对路径})))app.use(async (ctx, next) => {    if (ctx.path === '/' && ctx.method === 'GET') {        ctx.set('Content-Type', 'text/html;charset=utf8');        ctx.body = `        <form action="/" method="post" enctype="multipart/form-data">            <input type="text" name="username" autoComplete="off">            <input type="text" name="password" autoComplete="off">            <input type="file" name="avatar">            <input type="submit" >        </form>        `    } else {        return next();    }});app.use(async (ctx, next) => {    if (ctx.method === 'POST' && ctx.path === '/') {        // 获取表单提交过来的数据        ctx.body = ctx.request.fields;    }});app.listen(1000);复制代码
看下上传结果


内容也是正确的,我就不给大家展示拉
4、kao-views中间件
我们以ejs为例子
let Koa = require('koa');let app = new Koa();let views = require('koa-views');app.use(views(__dirname,{    extension:'ejs' //指定用ejs模板}));app.use(async (ctx,next)=>{    // 渲染index.ejs    await ctx.render('index',{name:'cgp',age:9,arr:[1,2,3]});});app.listen(3000);复制代码<!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>Document</title></head><body>    <h1><%=name%></h1>    <h1><%=age%></h1>    <ul>        <%arr.forEach(item=>{%>             <li><%=item%></li>        <%})%>    </ul></body></html>复制代码

5、koa-staticlet Koa = require('koa');let server = require('koa-static');let app = new Koa();app.use(server(__dirname +'/public'));app.listen(3000);复制代码6、koa自带cookie用法
比如我们要存储用户名,保留用户登录状态时,会用到cookie。
共两个方法
先来个demo测试,当输入/write写入cookie,当输入/read读到cookie
let Koa = require('koa');let Router = require('koa-router');let app = new Koa();let router = new Router();router.get('/read', (ctx, next) => {    //有name读name    let name = ctx.cookies.get("name") || '没有name';    let age = ctx.cookies.get("age") || '没有age';    ctx.body = `${name}-${age}`;});router.get('/write', (ctx, next) => {    ctx.cookies.set('name', 'cgp',{        domain:'127.0.0.1', //写入cookie所在的域名        path:'/write',    // 写入cookie最大的路径        maxAge:10*1000,    //Cookie最大有效时长        httpOnly:false,  // 是否只用于http请求中获取        overwrite:false  // 是否允许重写    });    ctx.cookies.set('age', '9');    ctx.body = 'write Ok';});app.use(router.routes());app.listen(4000);复制代码Cookie选项
看下运行结果吧


未完待续

作者:言sir
链接:https://juejin.im/post/5b5e780cf265da0f6b7713a8




作者: 不二晨    时间: 2018-8-16 17:24
奈斯




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2