1.搭建一个最简单的KOA服务器。
们初始化生产package.json 文件
npm
init
-
y
|
生成package.json后,安装koa包
|
npm
install
--
save
koa
|
index.js
const Koa = require("koa")
const app = new Koa();
app.use(async(ctx)=>{
ctx.body = "hello,world"
})
app.listen(3000);
console.log("app is start");
npm
init
-
y
|
2.接受get请求。
在koa2中GET请求通过request接收,但是接受的方法有两种:query和querystring。
- query:返回的是格式化好的参数对象。
- querystring:返回的是请求字符串。
如前端发出 http://127.0.0.1:3000/?a=1&id=2
demo1.js
const koa = require("koa");
const app = new koa();
app.use(async(ctx)=>{
let url = ctx.url;
//从request中获取GET请求
let request = ctx.request;
let req_query = request.query;
let req_querystring = request.querystring;
//从上下文中获取GET请求
let ctx_query = ctx.query;
let ctx_querystring = ctx.querystring;
ctx.body = { //打印到页面上
url,
req_query,
req_querystring,
ctx_query,
ctx_querystring
}
})
app.listen(3000,()=>{
console.log("app is start");
});
输出JSON:
{"url":"/?a=1&id=2","req_query":{"a":"1","id":"2"},"req_querystring":"a=1&id=2","ctx_query":{"a":"1","id":"2"},
"ctx_querystring":"a=1&id=2"}
ctx 对象:
{ method: 'GET',
url: '/',
header:
{ host: '127.0.0.1:3000',
connection: 'keep-alive',
'upgrade-insecure-requests': '1',
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36',
accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
dnt: '1',
'accept-encoding': 'gzip, deflate, sdch, br',
'accept-language': 'zh-CN,zh;q=0.8' } },
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>' }
{ request:
{ method: 'GET',
url: '/favicon.ico',
header:
{ host: '127.0.0.1:3000',
connection: 'keep-alive',
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36',
accept: 'image/webp,image/*,*/*;q=0.8',
dnt: '1',
referer: 'http://127.0.0.1:3000/',
'accept-encoding': 'gzip, deflate, sdch, br',
'accept-language': 'zh-CN,zh;q=0.8' } },
response: { status: 404, message: 'Not Found', header: {} },
app: { subdomainOffset: 2, proxy: false, env: 'development' },
originalUrl: '/favicon.ico',
req: '<original node req>',
res: '<original node res>',
socket: '<original node socket>' }
3.接受POST请求
对于POST请求的处理,Koa2没有封装方便的获取参数的方法,需要通过解析上下文context中的原生node.js请求对象req来获取。
获取Post请求的步骤:
- 解析上下文ctx中的原生nodex.js对象req。
- 将POST表单数据解析成query string-字符串.(例如:user=jspang&age=18)
- 将字符串转换成JSON格式。
ctx.request和ctx.req的区别
- ctx.request:是Koa2中context经过封装的请求对象,它用起来更直观和简单。
- ctx.req:是context提供的node.js原生HTTP请求对象。这个虽然不那么直观,但是可以得到更多的内容,适合我们深度编程。
ctx.method 得到请求类型
Koa2中提供了ctx.method属性,可以轻松的得到请求的类型,然后根据请求类型编写不同的相应方法,这在工作中非常常用。我们先来作个小例子,根据请求类型获得不同的页面内容。GET请求时得到表单填写页面,POST请求时,得到POST处理页面。
demo2.js
const koa = require("koa");
const app = new koa();
app.use(async(ctx)=>{
if(ctx.url==='/' && ctx.method==="GET"){
let html = `<form method="post" action="/">
<p>usename:<input type="text" name="usename"></p>
<p>age:<input type="text" name="age"></p>
<p>site:<input type="text" name="site"></p>
<button type="submit" >submit</button>
</form>`;
ctx.body=html;
}else if(ctx.url==='/' && ctx.method==="POST"){
//ctx.body = "POST"
let postData =await parsePostData(ctx);
ctx.body = postData
}else{
ctx.body = "404"
}
})
function parsePostData(ctx){
return new Promise((resolve,reject)=>{
try{
let postdata = '';
ctx.req.addListener("data",(data)=>{
postdata += data;
});
ctx.req.on('end',function(){//监听数据结束时,对数据传出去
let postData = parseQuerystr(postdata)
resolve(postData)
})
}catch(error){
reject(error)
}
})
}
function parseQuerystr(querystr){
let queryData = {};
let queryStrlist = querystr.split("&");
for(let itemquery of queryStrlist){
let queryDatalist = itemquery.split("=");
queryData[queryDatalist[0]] =decodeURIComponent(queryDatalist[1]) ;
}
return(queryData)
}
app.listen(3000,()=>{
console.log("domo2 server is start");
})
输出: { "usename" : "long" , "age" : " 30 " , "site" : "www.baidu.com" }
4.koa-bodyparser中间件
npm install --save koa-bodyparser
引入使用
安装完成后,需要在代码中引入并使用。我们在代码顶部用require进行引入。
1
|
const
bodyParser
=
require
(
'koa-bodyparser'
)
;
|
然后进行使用,如果不使用是没办法调用的,使用代码如下。
1
|
app
.
use
(
bodyParser
(
)
)
;
|
在代码中使用后,直接可以用ctx.request.body进行获取POST请求参数,中间件自动给我们作了解析。
demo3.js
const koa = require("koa");
const app = new koa();
const koaBody = require("koa-bodyparser")
app.use(koaBody());
app.use(async(ctx)=>{
if(ctx.url==='/' && ctx.method==="GET"){
let html = `<form method="post" action="/">
<p>usename:<input type="text" name="usename"></p>
<p>age:<input type="text" name="age"></p>
<p>site:<input type="text" name="site"></p>
<button type="submit" >submit</button>
</form>`;
ctx.body=html;
}else if(ctx.url==='/' && ctx.method==="POST"){
//ctx.body = "POST"
let postData =ctx.request.body;
ctx.body = postData
}else{
ctx.body = "404"
}
})
{
"usename"
:
"long1"
,
"age"
:
"
30
"
,
"site"
:
"www.baidu.com"
}
5Koa2原生路由实现
ctx.request.url 获取路径 如:/name
原生路由的实现需要引入fs模块来读取文件。然后再根据路由的路径去读取,最后返回给页面,进行渲染。
domo4.js
const koa = require("koa")
const app = new koa();
const fs = require("fs");
function render(page){
return new Promise((resolve,reject)=>{
let pageURL = './page/'+page;
fs.readFile(pageURL,'binary',(err,data)=>{
if(err){
reject(err);
}else{
resolve(data);
}
})
})
}
async function route(url){
let page = '404.html';
switch(url){
case '/':
page = 'index.html';
break;
case '/index.html':
page = 'index.html';
break;
case '/todo.html':
page = 'todo.html';
break;
case '/404.html':
page = '404.html';
break;
default:
break;
}
let html =await render(page);
return html
}
app.use(async(ctx)=>{
let url = ctx.request.url;
let html = await route(url)
console.log(html)
ctx.body = html;
});
app.listen(3000)
6.Koa-router中间件
安装koa-router中间件
1
|
npm
install
--
save
koa
-
router
|
const Koa = require('koa');
const Router = require('koa-router');
const app = new Koa();
const router = new Router();
router.get('/', function (ctx, next) {
ctx.body="Hello JSPang";
})
.get('/todo',(ctx,next)=>{
ctx.body="Todo page"
});
app
.use(router.routes())
.use(router.allowedMethods());
app.listen(3000,()=>{
console.log('starting at port 3000');
});
设置前缀
有时候我们想把所有的路径前面都再加入一个级别,比如原来我们访问的路径是http://127.0.0.1:3000/todo,现在我们希望在所有的路径前面都加上一个jspang层级,把路径变成http://127.0.0.1:3000/jspang/todo.这时候就可以使用层级来完成这个功能。路由在创建的时候是可以指定一个前缀的,这个前缀会被至于路由的最顶层,也就是说,这个路由的所有请求都是相对于这个前缀的。
1
2
3
|
const
router
=
new
Router
(
{
prefix
:
'/js'
}
)
|
写上这句代码,这时候你的访问路径就加了一个层级jspang。可以在浏览器中输入:http://127.0.0.1:3000/js/测试一下。
路由层级
例如这种写法装载路由层级,这里的router相当于父级:router.use(‘/page’, page.routes(), page.allowedMethods())。
代码如下:我们声明了两个路由,第一个是home,第二个是page.然后通过use赋予不同的前层级。
demo6.js
const koa = require('koa');
const app = new koa();
const Router = require("koa-router");
//主路由
let home = new Router();
home.get('/js',async(ctx)=>{
ctx.body = "js";
}).get('/vue',async(ctx)=>{
ctx.body = "vue"
});
let page = new Router();
page.get('/js',async(ctx)=>{
ctx.body = "js";
}).get('/vuex',async(ctx)=>{
ctx.body = "vuex"
});
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,()=>{console.log('app is start')});
参数
demo7.js
const koa = require('koa');
const Router = require("koa-router");
const app = new koa();
const router = new Router();
router.get('/',(ctx,next)=>{
ctx.body = ctx.query;
})
app.use(router.routes()).use(router.allowedMethods());
app.listen(3000,()=>{
console.log('app is start');
});
地址栏:http://127.0.0.1:3000/?a=1&v=2
输出:{"a":"1","v":"2"}
7.Koa2中使用cookie
开发中制作登录和保存用户信息在本地,最常用的就是cookie操作。比如我们在作一个登录功能时,希望用户在接下来的一周内都不需要重新登录就可以访问资源,这时候就需要我们操作cookie来完成我们的需求。koa的上下文(ctx)直接提供了读取和写入的方法。
- ctx.cookies.get(name,[optins]):读取上下文请求中的cookie。
- ctx.cookies.set(name,value,[options]):在上下文中写入cookie。
demo8.js
const koa = require("koa");
const app = new koa();
app.use(async(ctx)=>{
if(ctx.url==="/index"){
ctx.cookies.set('name','johnson',{
domain:'127.0.0.1',
//path:'/index',
maxAge:1000*60*60*60,
expires:new Date("2018-12-1"),
httpOnly:false,
overwrite:false
});
ctx.
body=
"cookies is OK"
}
else{
ctx.
body=
"hello.world";
if(
ctx.
cookies.
get(
"name"))
{
ctx.
body=
ctx.
cookies.
get(
"name")
}
else{
ctx.
body=
"no cookie"
}
}
})
app.
listen(
3000,()
=>{
console.
log(
"app is start");
});
ookie选项
比如我们要存储用户名,保留用户登录状态时,你可以选择7天内不用登录,也可以选择30天内不用登录。这就需要在写入是配置一些选项:
domain:写入cookie所在的域名
path:写入cookie所在的路径
maxAge:Cookie最大有效时长
expires:cookie失效时间
httpOnly:是否只用http请求中获得
overwirte:是否允许重写
8.EJS模板
安装中间件
在koa2中使用模板机制必须依靠中间件,我们这里选择koa-views中间件,先使用npm来进行安装。
1
cnpm
install
--
save
koa
-
views
安装ejs模板引擎
ejs是个著名并强大的模板引擎,可以单独安装。很多开源软件都采用了ejs模板引擎。
1
npm
install
--
save
ejs
编写模板
安装好ejs模板引擎后,就可以编写模板了,为了模板统一管理,我们新建一个view的文件夹,并在它下面新建index.ejs文件。
views/index.ejs
1
2
3
4
5
6
7
8
9
10
<!DOCTYPE html>
<html>
<head>
<title>
<%=
title
%>
</title>
</head>
<body>
<h1>
<%=
title
%>
</h1>
<p>
EJS Welcome to <%= title %>
</p>
</body>
</html>
详细解释在视频中讲解。
编写koa文件
有了模板文件,我们需要在js文件中配置并渲染。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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
)
=
>
{
let
title
=
'hello koa2'
await
ctx
.
render
(
'index'
,
{
title
}
)
}
)
app
.
listen
(
3000
,
(
)
=
>
{
console
.
log
(
'[demo] server is starting at port 3000'
)
;
}
)
9.访问静态资源
安装koa-static:
使用npm进行安装中间件,讲课时使用的是4.0.2版本。
1
npm
install
--
save
koa
-
static
新建static文件夹
然后在static文件中放入图片,css和js文件。
const Koa = require("koa");
const app = new Koa();
const static = require('koa-static');
const path = require('path');
const staticPath = './static'
app.use(static(path.join(__dirname,staticPath)));
app.use(async(ctx)=>{
ctx.body = 'hello';
});
app.listen(3000,()=>{
console.log('app ok')
})