Koa基礎(chǔ):Koa的基礎(chǔ)介紹

1. Koa的安裝和搭建:

1.1 項(xiàng)目初始化:

npm init會生成配置文件package.json刃永,用于管理項(xiàng)目中用到的一些安裝包。

1.2 安裝Koa:

npm install koa --save

1.3 編寫app.js谨垃,啟動服務(wù):

簡單編寫一個app.js應(yīng)用程序:

const koa = require('koa');
const app = new koa();
app.use(async (ctx, next)=>{
    ctx.response.body = '<h1>Hello World</h1>';
});
app.listen(3000, ()=>{
    console.log('server is running at port 3000.');
})

node app.js啟動服務(wù),訪問本地 http://localhost:3000會看到Hello World。
當(dāng)然便于項(xiàng)目的調(diào)試和服務(wù)在線運(yùn)行的穩(wěn)定影斑,建議使用pm2啟動Koa服務(wù)瞬浓。

2. Context對象:

context成為‘上下文’初婆,在Koa中Nodejs的原生request和response對象都封裝到了context對象中,Koa應(yīng)用程序的每個請求都將創(chuàng)建一個context猿棉,并在中間件中作為參數(shù)被引用磅叛。
下面列舉一些經(jīng)常用到的context屬性值:

2.1 ctx.request
  • ctx是context的簡寫,ctx.request是Koa的request對象萨赁,看一段代碼宪躯,看一下GET請求數(shù)據(jù)是怎么獲取和解析的:
const koa = require('koa');
const app = new koa();
app.use(async (ctx, next)=>{
    ctx.response.body = {
        url: ctx.request.url,     //獲取請求的URL
        query: ctx.request.query,    //獲取get請求的解析數(shù)據(jù)
        querystring: ctx.request.querystring    //獲取原始get請求的字符串
    }
})

node app.js啟動應(yīng)用,訪問http://localhost:3000/?search=koa&keywords=context位迂,便可以看到返回的響應(yīng):

{
    "url": "/?search=koa&keywords=context",
    "query":{"search":"koa", "keywords":"context"},
    "querystring":"search=koa&keywords=context"
}
  • 有GET請求數(shù)據(jù)的獲取访雪,比然有POST數(shù)據(jù)的獲取和解析详瑞,原生nodejs中獲取POST請求的方式比較繁瑣(可自行搜索一下,其實(shí)不復(fù)雜)臣缀,這里直接引用koa-bodyparser中間件:
    npm install koa-bodyparser --save安裝該中間件坝橡,下面通過一個簡單的表單提交測試koa-bodyparser如何獲取post數(shù)據(jù)的:
const koa = require('koa');
const bodyParser = require('koa-bodyparser');
const app = new koa();
app.use(bodyParser());
app.use(async (ctx, next)=>{
    //解析后的post數(shù)據(jù)會存儲在ctx.request.body中,如果沒有數(shù)據(jù)則為空對象
    ctx.body = ctx.request.body;
})
app.listen(3000, ()=>{
    console.log('server is running at port 3000');
})

后面結(jié)合router路由精置,通過一個form表單來測試一下效果计寇。

2.2 ctx.response

ctx.response是Koa的response對象,其中包含了幾個常用的屬性:

  • ctx.response.body:返回給用戶的響應(yīng)主體脂倦。
  • ctx.response.status:設(shè)置響應(yīng)狀態(tài)碼(如200番宁、404、500等)赖阻。在實(shí)際開發(fā)中蝶押,除了設(shè)置一個請求的響應(yīng)主體外,往往還要設(shè)置響應(yīng)狀態(tài)碼火欧。
  • ctx.response.type:設(shè)置響應(yīng)的Content-Type棋电,顯示地設(shè)置Content-Type是因?yàn)闉g覽器默認(rèn)地Content-Type是text/plain,如果Content-Type不對會發(fā)生解析錯誤苇侵。如果響應(yīng)內(nèi)容是HTML赶盔,則設(shè)置為ctx.response.type='html';如果響應(yīng)地是png圖片榆浓,則ctx.response.type='image/png'于未。
2.3 ctx.state

ctx.state是推薦地命名空間,用于通過中間件傳遞信息和前端視圖陡鹃。例如koa-views這些渲染Views視圖層地中間件會默認(rèn)把ctx.state里面地屬性作為視圖模板的參數(shù)傳入烘浦。

2.4 ctx.cookies

ctx.cookies用于獲取和設(shè)置Cookie。

ctx.cookies.get(name, [options]);    //獲取Cookie
ctx.cookies.set(name, value, [options]);    //設(shè)置Cookie

其中options配置如下:

  • maxAge: /ms為單位的過期時間
  • signed: Cookie簽名值
  • expires: Cookie過期的Date
  • path: Cookie路徑杉适,默認(rèn)/
  • domain: Cookie域名
  • secure: 安全Cookie谎倔,只能使用https協(xié)議
  • httpOnly: true則Cookie無法被javascript獲取到
  • overwrite: 布爾值,是否覆蓋以前設(shè)置的同名Cookie猿推,默認(rèn)false
2.5 ctx.throw

ctx.throw用于拋出錯誤片习,把錯誤信息返回給用戶:

app.use(async (ctx)=>{
    ctx.throw(500);   //將響應(yīng)500錯誤
})

3. Koa中間件:

3.1 理解中間件的概念:

先來看下面這段代碼:

app.use(async (ctx, next)=>{
    console.log(ctx.method, ctx.host+ctx.url);    //打印請求方法、主機(jī)名蹬叭、URL
    await next();
    ctx.body = 'Hello World';
})

上述代碼可以打印日志藕咏,返回'Hello World',其實(shí)可以將其中打印日志的部分功能抽象成一個logger函數(shù):

const logger = async function(ctx, next){
    console.log(ctx.method, ctx.host+ctx.url);
    await next();
}
app.use(logger);    //使用app.use()加載中間件
app.use(async (ctx, next) => {
    ctx.body = 'Hello World';
})

像上面抽象出來的logger函數(shù)就是中間件秽五,通過app.use()來加載中間件孽查。

3.2 koa-bodyparser中間件:

對于post請求的數(shù)據(jù)獲取,原生nodejs使用了req對象監(jiān)聽data事件并將其拼接得到坦喘,比較繁瑣盲再。而koa-bodyparser可以直接把post數(shù)據(jù)解析到ctx.request.body中西设,先安裝npm install koa-bodyparser --save,然后通過一個表單提交來測試一下:

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

app.use(bodyParser());
app.use(async (ctx, next)=>{
    if(ctx.url == '/' && ctx.request.method == 'GET'){
        ctx.request.type = 'html';
        let html = `
        <h2>登錄</h2>
        <form action="/" method="POST">
            <p>用戶名:</p>
            <input name="name" /></br>
            <p>密碼:</p>
            <input name="password" type="password" /></br>
            <button type="submit">Submit</button>
        </form>
        `
        ctx.body = html;
    }else if(ctx.url=='/' && ctx.request.method=='POST'){
        let postData = ctx.request.body;
        ctx.body = postData;
    }
})

提交表單數(shù)據(jù)后答朋,將會看到bodyParser解析的post數(shù)據(jù)對象贷揽。

3.3 koa-router中間件:

上面登錄表單的例子通過ctx.url判斷路徑,通過ctx.request.method判斷請求方式梦碗,然而這種手動判斷路由的方法禽绪,隨著后面各種各樣的業(yè)務(wù)增多,會嚴(yán)重影響代碼的可讀性和可維護(hù)性洪规,借助于koa-router中間件印屁,能清晰簡單的處理各種請求路由,先安裝npm install koa-router --save斩例,具體用法如下面代碼:

const koa = require('koa');
const bodyParser = require('koa-bodyparser');
const router = require('koa-router')();
const app = new koa();

app.use(bodyParser());
router.get('/', (ctx, next)=>{
    // 登陸頁雄人,省略
});

router.post('/', (ctx, next)=>{
    let postData = ctx.request.body;
    ctx.body = postData;
});
app.use(router.routes());    //加載router中間件
app.use(router.allowedMethods());    //對異常狀態(tài)碼的處理

上面的代碼中,直接通過router.get('uri')router.post('uri')來處理GET和POST請求的uri樱拴,不需要再進(jìn)行手動判斷了柠衍。

3.3.1 koa-router獲取GET請求的傳值:

koa-router將原生的nodejs的request封裝在ctx中:

  • ctx.query:返回的是格式化好的參數(shù)對象
  • ctx.querystring:返回的是請求字符串
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 koa";
})
router.get('/newscontent',(ctx,next)=>{
  let url =ctx.url;
  //從request 中獲取GET 請求
  let request =ctx.request;
  let req_query = request.query;
  let req_querystring = request.querystring;
  //從上下文中直接獲取
  let ctx_query = ctx.query;
  let ctx_querystring = ctx.querystring;
  ctx.body={
    url,
    req_query,
    req_querystring,
    ctx_query,
    ctx_querystring
  }
});
app.use(router.routes()); //作用:啟動路由
app.use(router.allowedMethods()); //作用: 當(dāng)請求出錯時的處理邏輯
app.listen(3000,()=>{
  console.log('starting at port 3000');
});
3.3.2 koa-router獲取URI動態(tài)傳值:
//請求方式http://域名/product/123
router.get('/product/:aid',async (ctx)=>{
  console.log(ctx.params); //{ aid: '123' } //獲取動態(tài)路由的數(shù)據(jù)
  ctx.body='這是商品頁面';
});
3.4 koa-static中間件和koa-views中間件
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末洋满,一起剝皮案震驚了整個濱河市晶乔,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌牺勾,老刑警劉巖正罢,帶你破解...
    沈念sama閱讀 222,104評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異驻民,居然都是意外死亡翻具,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,816評論 3 399
  • 文/潘曉璐 我一進(jìn)店門回还,熙熙樓的掌柜王于貴愁眉苦臉地迎上來裆泳,“玉大人,你說我怎么就攤上這事柠硕」ず蹋” “怎么了?”我有些...
    開封第一講書人閱讀 168,697評論 0 360
  • 文/不壞的土叔 我叫張陵蝗柔,是天一觀的道長闻葵。 經(jīng)常有香客問我,道長癣丧,這世上最難降的妖魔是什么槽畔? 我笑而不...
    開封第一講書人閱讀 59,836評論 1 298
  • 正文 為了忘掉前任,我火速辦了婚禮胁编,結(jié)果婚禮上厢钧,老公的妹妹穿的比我還像新娘鳞尔。我一直安慰自己,他們只是感情好早直,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,851評論 6 397
  • 文/花漫 我一把揭開白布铅檩。 她就那樣靜靜地躺著,像睡著了一般莽鸿。 火紅的嫁衣襯著肌膚如雪昧旨。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,441評論 1 310
  • 那天祥得,我揣著相機(jī)與錄音兔沃,去河邊找鬼。 笑死级及,一個胖子當(dāng)著我的面吹牛乒疏,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播饮焦,決...
    沈念sama閱讀 40,992評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼怕吴,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了县踢?” 一聲冷哼從身側(cè)響起转绷,我...
    開封第一講書人閱讀 39,899評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎硼啤,沒想到半個月后议经,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,457評論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡谴返,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,529評論 3 341
  • 正文 我和宋清朗相戀三年煞肾,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片嗓袱。...
    茶點(diǎn)故事閱讀 40,664評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡籍救,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出渠抹,到底是詐尸還是另有隱情蝙昙,我是刑警寧澤,帶...
    沈念sama閱讀 36,346評論 5 350
  • 正文 年R本政府宣布逼肯,位于F島的核電站耸黑,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏篮幢。R本人自食惡果不足惜大刊,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,025評論 3 334
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧缺菌,春花似錦葫辐、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,511評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至焊傅,卻和暖如春剂陡,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背狐胎。 一陣腳步聲響...
    開封第一講書人閱讀 33,611評論 1 272
  • 我被黑心中介騙來泰國打工鸭栖, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人握巢。 一個月前我還...
    沈念sama閱讀 49,081評論 3 377
  • 正文 我出身青樓晕鹊,卻偏偏與公主長得像,于是被迫代替她去往敵國和親暴浦。 傳聞我的和親對象是個殘疾皇子溅话,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,675評論 2 359

推薦閱讀更多精彩內(nèi)容