# koa2 **Repository Path**: josnfei/koa2 ## Basic Information - **Project Name**: koa2 - **Description**: koa2学习--前端码仔学习后端必走之路 - **Primary Language**: NodeJS - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 2 - **Forks**: 0 - **Created**: 2018-06-25 - **Last Updated**: 2023-09-05 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README ## koa2学习笔记 #### 搭建环境 - 安装Node.js - 搭建环境 + cd code //进入code文件夹 + mkdir koa2 //创建koa2文件夹 + cd koa2 //进入koa2文件夹 + npm init -y - 安装koa包 + npm install --save koa - 编写代码 + 运行node index.js #### async/await的使用方法 - 个人理解 + async可以写异步函数 ,返回的是一个promise + await 是等这个异步执行后才会执行,并且必须放在async里面使用 ```javascript function takeLongTime(){ return new Promise(resolve=>{ setTimeout(()=>{ resolve('long_time_value') },2000) }) } async function test(){ const v= await takeLongTime() console.log(v); //返回的是promise } test(); ``` #### 第03节:Get请求的接收 - 干嘛用的? + 可以获得前端发送过来的请求的参数 - 获得GET请求的方式有两种 + 一种是从request中获得(格式两种) + ctx.request.query + ctx.request.querystring + 一种是一直从上下文中获得(格式两种) + ctx.query + ctx.querystring - 获得的格式也有两种区别 + query (返回的是对象形式) + {user:Dfei,age:18} + querystring (返回的是字符串形式) + user=Dfei&age=18 ```javascript // 第03节:Get请求的接收 const Koa=require('koa'); const App=new Koa(); App.use(async (ctx)=>{ console.log(ctx); let url=ctx.url; //获取请求的地址 //返回 /?user=Dfei&age=18 形式 //从request中获取GET请求 let request=ctx.request; let req_query=request.query; //返回GET请求的URL的参数,形式是对象 {user:Dfei,age:18} let req_querystring=request.querystring //返回GET请求的URL的参数 形式是字符串 user=Dfei&age=18 // 从上下文中直接获取 let ctx_query=ctx.query; //{user:Dfei,age:18} let ctx_querystring=ctx.querystring //user=Dfei&age=18 ctx.body={ url, req_query, req_querystring, ctx_query, ctx_querystring } }) // 浏览器访问 127.0.0.1:3000?user=Dfei&age=18 App.listen(3000,()=>{ console.log('服务器已启动') }) /** * 总结:获得GET请求的方式有两种,一种是从request中获得,一种是一直从上下文中获得。获得的格式也有两种:query和querystring。大家要区分记忆,并根据实际需求进行灵活变换。 */ ``` #### 第04,05节:POST请求如何接收(1,2) - koa如何获取用户是什么请求? + ctx.method的方式,可以获取到是GET还是POST请求方式 - koa2如何处理POST 前端传过来的参数? + 原生方法,也就是不使用中间件的方法,看代码 ```javascript // 第05节:POST请求如何接收(2) 如何处理post前端传过来的参数 const Koa=require('koa'); const App=new Koa(); App.use(async (ctx)=>{ // GET请求 if(ctx.url=='/'&&ctx.method=='GET'){ let html=`

Koa2 request post demo

userName


age


webSite


`; ctx.body=html; }else if(ctx.url=='/'&&ctx.method=='POST'){ // post请求处理 ctx.body=await parsePostData(ctx); //返回请求的参数?主要体现在这个函数里面 }else{ ctx.body='404未找到该页面' } }) // 处理前端post传过来的参数 function parsePostData(ctx){ return new Promise((resolve,reject)=>{ try{ let postdata=''; ctx.req.on('data',(data)=>{ //在这里监听 拿post的参数拼接起来 postdata+=data }) // console.log(postdata,'拼接') ctx.req.addListener('end',function(){ //监听完成 let parseData=parseQueryStr(postdata) // console.log(parseData,'完成') resolve(parseData) }) }catch(error){ reject(error) } }) } // url参数获取函数,返回的是组装好的对象 // userName=acb&age=12&webSite=hello+world 处理成 { userName: 'acb', age: '12', webSite: 'hello+world' } function parseQueryStr(queryStr){ // console.log(queryStr) let queryData={}; let queryStrList = queryStr.split('&'); // console.log(queryStrList); for( let [index,queryStr] of queryStrList.entries() ){ let itemList = queryStr.split('='); // console.log(itemList); queryData[itemList[0]] = decodeURIComponent(itemList[1]); } return queryData } App.listen(3000,()=>{ console.log('post请求的服务器已经启动') }) ``` #### 第06节:koa-bodyparser中间件 - 干嘛用的??? + 快速获取前端POST请求传递过来的参数 - 使用步骤 + 1. 下载包 `npm i --save koa-bodyparser` + 2. 引入包 `const bodyParser=require(koa-bodyparser)` + 3. 使用1 `App.use(bodyParser())` + 4. 使用2 `ctx.request.body` 中可以获取post发送过来的参数 - 注意点 + 不管是否是fromData的方式的post请求,还是类似正常的AJAX的post,都可以通过这个拿到请求的参数 - 补充1个知识,就是解决跨域问题需要的中间件 + 安装 `npm install --save koa2-cors` 中间件 + 使用 `App.use(cors())` ```javascript // 第06节:koa-bodyparser中间件 // 作用: 对于POST请求的处理,koa-bodyparser中间件可以把koa2上下文的formData数据解析到ctx.request.body中。 // 注意,这里说的是formData ,也就是说表单的形式,传过来的是age=12&name=Dfei 这种形式,其他形式用哪个中间件,暂时未知(已得到答案,一样用这个,jq的方法测试过,没毛病) const Koa = require('koa'); const App = new Koa(); const bodyParser = require('koa-bodyparser'); //处理类似表单formData的方式传递过来的参数的中间件 npm install --save koa-bodyparser@3 // 直接可以用ctx.request.body进行获取POST请求参数 // 另外加n 支持跨域请求 npm install --save koa2-cors const cors=require('koa2-cors') // 允许跨域 App.use(cors()) App.use(bodyParser()); App.use(async(ctx)=>{ if(ctx.url==='/' && ctx.method==='GET'){ //显示表单页面 let html=`

JSPang Koa2 request POST

userName


age


website


`; ctx.body=html; }else if(ctx.url==='/' && ctx.method==='POST'){ let postData= ctx.request.body; ctx.body=postData; }else{ ctx.body='

404!

'; } }); App.listen(3000,()=>{ console.log('服务已启动,端口号3000'); }); // 总结(必看) // post获取穿过来的参数 // 利用koa-bodyparser可以获得post传过来的参数,是对象的形式 // 通过ctx.request.body获取 // get 获取传过来的参数通过 /** * * 从request中获取GET请求 let request=ctx.request; let req_query=request.query; //返回GET请求的URL的参数,形式是对象 {user:Dfei,age:18} let req_querystring=request.querystring //返回GET请求的URL的参数 形式是字符串 user=Dfei&age=18 // 从上下文中直接获取 let ctx_query=ctx.query; //{user:Dfei,age:18} let ctx_querystring=ctx.querystring //user=Dfei&age=18 */ ``` #### 第08节:Koa-router中间件(1)入门 - 干嘛用的??? + 用来接收前端请求的路径,和之前常用的 `App.use( async(ctx)=>{ if(ctx.url=='/') } )` 方式是一样的,只是这个中间件用的更方便,功能多 - 使用步骤 + 1. 安装 `npm i --save koa-router` + 2. 实例化 `const router=new Router();` + 3. 使用 `router.get('/',function(ctx,next){}).get('/index',()=>{})` 有多个则继续写下去,Post请求也是继续往后写 + 4. 加载中间件 `App.use(router.routes()) .use(router.allowedMethods());` 这个是必写的 ```javascript // 第08节:Koa-router中间件(1)入门 var Koa=require('koa'); var Router=require('koa-router'); //路由 var App=new Koa(); const router=new Router(); // 基础案例 router.get('/',function(ctx,next){ ctx.body="Hello Dfei" }) // 多页面配置 其实多页面的添加只要继续在下面填写get或者Post就可以了,比如我们再加一个todo的页面 .get('/todo',function(ctx,next){ ctx.body='Hello zhouwenfei' }) App.use(router.routes()) .use(router.allowedMethods()); App.listen(3000,function(){ console.log('服务器已启动') }) // 总结: // 总结:我们可以发现有了中间件进行配置路由非常简单,但是路由还是很复杂的,今天讲的只是koa-router最基本的用法,我们会在下面几节课中不断增加难度。 ``` #### 第09节:Koa-router中间件(2)层级 - 层级是什么意思? + 设置前缀 + 比如: 有时候我们想把所有的路径前面都再加入一个级别,比如原来我们访问的路径是http://127.0.0.1:3000/todo,现在我们希望在所有的路径前面都加上一个jspang层级,把路径变成http://127.0.0.1:3000/jspang/todo.这时候就可以使用层级来完成这个功能。路由在创建的时候是可以指定一个前缀的,这个前缀会被至于路由的最顶层,也就是说,这个路由的所有请求都是相对于这个前缀的 - 其他看代码吧,语言无法表达 ```javascript // 第09节:Koa-router中间件(2)层级 const Koa=require('koa'); const Router=require('koa-router'); const App=new Koa() const router=new Router({ prefix:'/Dfei' //设置前缀 }); // 设置前缀说明 /** * 有时候我们想把所有的路径前面都再加入一个级别,比如原来我们访问的路径是http://127.0.0.1:3000/todo,现在我们希望在所有的路径前面都加上一个jspang层级,把路径变成http://127.0.0.1:3000/jspang/todo.这时候就可以使用层级来完成这个功能。路由在创建的时候是可以指定一个前缀的,这个前缀会被至于路由的最顶层,也就是说,这个路由的所有请求都是相对于这个前缀的。 */ router.get('/dfei',(ctx,next)=>{ ctx.body='DFEI' }) // 需求 /** * 设置前缀一般都是全局的,并不能实现路由的层级,如果你想为单个页面设置层级,也是很简单的。只要在use时使用路径就可以了。 例如这种写法装载路由层级,这里的router相当于父级:router.use(‘/page’, page.routes(), page.allowedMethods())。 通过这种写法的好处是并不是全局的,我们可以给不同的路由加层级。 代码如下:我们声明了两个路由,第一个是home,第二个是page.然后通过use赋予不同的前层级。 * */ // 两个子路由 const home=new Router() home.get('/dfei',(ctx,next)=>{ ctx.body='Home dfei' }) .get('/todo',(ctx,next)=>{ ctx.body='Home todo' }) const page=new Router(); page.get('/dfei',(ctx,next)=>{ ctx.body='page dfei' }) .get('/todo',(ctx,next)=>{ ctx.body='page todo' }) // 转载所有子路由 const routers=new Router(); routers.use('/home',home.routes(),home.allowedMethods()); //浏览器访问: 127.0.0.1:3000/home/dfei 127.0.0.1:3000/home/todo routers.use('/page',page.routes(),page.allowedMethods()); //浏览器访问: 127.0.0.1:3000/page/dfei 127.0.0.1:3000/page/todo // 加载路由中间件 App.use(router.routes()).use(router.allowedMethods()); //全局的路由中间件 // 加载路由中间件 App.use(routers.routes()).use(routers.allowedMethods()); //刚才分开的路由中间件 App.listen(3000,()=>{ console.log('服务已启动') }) ``` #### 第10节:Koa-router中间件(3)参数(总结) - 实际是前几节的内容,当总结了 - 前端GET请求发送过来的参数如何获取 (两种方法,每种方法又有两种模式,可看第三节) - 前端POST请求发送过来的参数如何获取(`koa-bodyparser中间件`) - `koa-router`中间件的时候,别忘了最后需要加载路由中间件,也就是`App.use(router.routes()) .use(router.allowedMethods());` ```javascript // 第10节:Koa-router中间件(3)参数 const Koa=require('koa'); const Router=require('koa-router'); //路由中间件 const bodyParser=require('koa-bodyparser'); //post请求获取前端传过来的参数 使用 ctx.request.body const App=new Koa(); const router=new Router(); App.use(bodyParser()) ; //使用koa-bodyparsr 中间件 router.get('/dfei',(ctx,next)=>{ //浏览器访问:http://localhost:3000/dfei?name=wenfei&age=19 即可监听到这个/dfei请求 console.log(ctx.query,'get传后台的参数'); //获取get请求的传递过来的恩参数 console.log(ctx.url); //如果http://localhost:3000/dfei?name=wenfei&age=19 得到 /dfei?name=wenfei&age=19 如果 如果http://localhost:3000/dfei 得到 /dfei let html=`

Koa2 request post demo

userName


age


webSite


`; ctx.body=html }) .post('/post',(ctx,next)=>{ console.log(ctx.request.body,'前端post传过来的参数') ctx.body=ctx.request.body; }) // 加载路由中间件 App.use(router.routes()) .use(router.allowedMethods()); App.listen(3000,()=>{ console.log('服务启动成功') }) ``` #### 第11节:Koa2中使用cookie - 干嘛用的? + 保存cookie - 方法 + 获取 + `ctx.cookies.get(name,[optins])`:读取上下文请求中的cookie。 + 设置 + `ctx.cookies.set(name,value,[options])`:在上下文中写入cookie。 - 注意点 + 设置时候的options里面的path的设置是否必须,看代码注释 ```javascript // 第11节:Koa2中使用cookie /** *开发中制作登录和保存用户信息在本地,最常用的就是cookie操作。比如我们在作一个登录功能时,希望用户在接下来的一周内都不需要重新登录就可以访问资源,这时候就需要我们操作cookie来完成我们的需求。koa的上下文(ctx)直接提供了读取和写入的方法。 * */ /** cookie方法使用 * * 获取: * ctx.cookies.get(name,[optins]):读取上下文请求中的cookie。 * * 设置: * ctx.cookies.set(name,value,[options]):在上下文中写入cookie。 * * */ const Koa=require('koa'); const App=new Koa(); App.use(async (ctx)=>{ if(ctx.url=='/index'){ ctx.cookies.set( 'myName','Dfei',{ domain:'localhost', //写COOKIE所在的域名 就算你是在Localhost这个域名下,我也不会生成这个cookie path:'/index', //写cookie所在的路径 如果访问的是localhost:3000/aa,则读取不到cookie,访问localhost:3000/index/aa,就可以拿到。 这就是这个path路径搞的鬼, 这里注意一下,如果需要全局,path配/就可以了 maxAge:1000*60*60*24*365, //cookie有效期 expires:new Date('2019-12-1'), //cookie失效时间 httpOnly:false, //是否只用于http请求 overwrite:false, //是否允许重写 } ) ctx.body=ctx.cookies.get('myName')+'cookie 已 OK' }else{ if(ctx.cookies.get('myName')){ ctx.body=ctx.cookies.get('myName') }else{ ctx.body='cookie is no' } } }) App.listen(3000,()=>{ console.log('服务启动成功') }) ``` #### 第12节:Koa2的模板初识(ejs) - 干嘛用的??? + 返回前端html代码解析的模板引擎,类似art-template - 使用步骤(需要安装两个东西) + 1. 安装中间件 `cnpm install --save koa-views` 注意的是是koa-views 而不是koa-view + 引入:` const view=require('koa-views');` //在koa2中使用模板机制必须依靠中间件 + 使用:`App.use(view(path.join(__dirname,'./view'),{ extension:'ejs' //告诉她,我用的是哪个模板引擎 }))` + 2. 安装模板引擎 `npm install --save ejs` ```javascript // 第12节:Koa2的模板初识(ejs) /** * 安装中间件 (在koa2中使用模板机制必须依靠中间件,我们这里选择koa-views中间件,先使用npm来进行安装。) * cnpm install --save koa-views (注意的是是koa-views 而不是koa-view) * * * 安装ejs模板引擎 (ejs是个著名并强大的模板引擎,可以单独安装。很多开源软件都采用了ejs模板引擎。) * * npm install --save ejs * */ const Koa=require('koa'); const view=require('koa-views'); //在koa2中使用模板机制必须依靠中间件 const path=require('path'); //node里面的api,处理文件路径 const App=new Koa(); App.use(view(path.join(__dirname,'./view'),{ extension:'ejs' //告诉她,我用的是哪个模板引擎 })) App.use(async (ctx)=>{ let title='Dfei'; await ctx.render('index',{ //渲染 title }) }) App.listen(3000,()=>{ console.log('服务已启动') }) ``` #### 第13节:koa-static静态资源中间件 - 干嘛用的??? + 服务器返回给前端的静态资源。 + 比如,返回服务器IP加图片地址,可以访问到该图片 - 使用步骤 + 安装 `npm install --save koa-static` + 引入 ` const static=require('koa-static');` 静态资源中间件 + 使用,看代码 ```javascript // 第13节:koa-static静态资源中间件 /** * 在后台开发中不仅有需要代码处理的业务逻辑请求,也会有很多的静态资源请求。比如请求js,css,jpg,png这些静态资源请求。也非常的多,有些时候还会访问静态资源路径。用koa2自己些这些静态资源访问是完全可以的,但是代码会雍长一些。所以这节课我们利用koa-static中间件来实现静态资源的访问。 */ /** * 安装koa-static: * npm install --save koa-static * * 新建static文件夹 * */ 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'; }) //浏览器访问 127.0.0.1:3000/appShow.jpg 就可以访问到静态资源了 App.listen(3000,()=>{ console.log('启动成功') }) ```