2020-2-26-koa框架使用

SylvesterZhang發表於2024-03-22

快速上手、路由、動態路由、獲取get值、中間間、koa-views使用、ejs小結、利用中間體配置公共變數、獲取post資料、靜態web服務、koa-art-template使用、cookies使用、session使用、mongodb資料庫封裝、路由模組化案例、快速建立koa專案koa-generator

快速上手

1安裝

npm install koa --save

2使用

var koa=require('koa');//匯入模組

var app=new koa()//建立物件

app.use(async(ctx)=>{
    ctx.body="hello"
})

app.listen(3000)

路由

1安裝

npm install koa-roter --save

2使用路由後的程式碼

var koa=require('koa');
var router=require('koa-router')();//引入並例項化,不需要再new了

var app=new koa()

router.get('/',async(ctx)=>{//ctx,即contex,包含request,response等資訊
    ctx.body='首頁'//返回資料,相當於response.writeHead(),response.end('首頁')
    //ctx.redirect('/')//跳轉到'/'
})

app.use(router.routes())//配置路由
app.use(router.allowedMethods())

app.listen(3000)

動態路由

router.get('/newscontent/:id',async(ctx)=>{
    console.log(ctx.params)//{ id: '1' }
    ctx.body='新聞內容'
})

獲取get傳值

執行後,瀏覽器訪問127.0.0.1:3000?name=zhang

router.get('/',async(ctx)=>{
    console.log(ctx.query)//{ name: 'zhang' }
    console.log(ctx.querystring)//name=zhang
    console.log(ctx.request.query)//{ name: 'zhang' }
    console.log(ctx.request.querystring)//name=zhang
    ctx.body='首頁'
})

中介軟體

分為應用中介軟體、路由級中介軟體、錯誤處理中介軟體、第三方中介軟體

1應用中介軟體

//應用中介軟體
//1.無next引數
app.use(async (ctx)=>{
    ctx.body="你好"//無next引數將不再向下匹配路由
})

//2.有next引數
app.use(async (ctx,next)=>{
    ctx.body="你好"
    await next()//將會向下匹配路由,如果未匹配到則返回"你好"
})

2路由級中介軟體

router.get('/news',async(ctx,next)=>{
    console.log("第一次匹配")//執行
    ctx.body='第一次匹配結果'//後面同名路由如果有ctx.body,這裡不執行,否則執行
    await next()
})

router.get('/news',async(ctx)=>{
    console.log("第二次匹配")//執行
    ctx.body='第二次匹配結果'
})

3錯誤處理中介軟體

app.use(async (ctx,next)=>{
    console.log("錯誤處理中介軟體")//一次請求中,次句將會被執行兩次,類似洋蔥模型
    await next()
    if(ctx.status==404){
        ctx.body="找不到頁面"
    }else{
        console.log("無錯誤")
    }
})

4第三方中介軟體

其他中介軟體,需要用app.use進行配置


koa-views使用

1安裝

npm install koa-views --save
npm install ejs --save

2程式碼

var views=require('koa-views')

//注意:配置語句必須放置再路由之前
//app.use(views('./views',{extension:'ejs'}))//html檔案的字尾名必須是ejs
app.use(views('./views',{map:{html:'ejs'}}))//html檔案的字尾名必須是html

router.get('/',async(ctx)=>{
    await ctx.render('hello',{})
})

ejs使用小結

{% raw %}
<!--引入-->
<%- include('header') -%>

<!--變數-->
<%=name%><!--name是傳入的變數-->

<!--解析-->
<%-value%><!--解析value裡的html程式碼-->

<!--迴圈-->
<%for(item of list){%><!--js寫法-->
    <%=item%>
<%}%>
 
<!--判斷-->
<%if(num>20){%><!--js寫法-->
    <span>num大於20</span>	
<%}%>
{% endraw %}

利用中間體配置公共變數

app.use(async(ctx,next)=>{
    ctx.state.userinfo='zhang'
    await next()
})

所有html檔案均可訪問userinfo變數


獲取post資料

1原生方式

1)getpostdata.js

var querystring=require('querystring');

function getpostdata(ctx){
    return new Promise((resolve,reject)=>{
        try{
            let str=''
            ctx.req.on('data',(chunk)=>{
                str+=chunk
            })
            ctx.req.on('end',()=>{
                str=querystring.parse(str)
                resolve(str)
            })
        }catch(err){
            reject(err)
        }
    })
}
module.exports=getpostdata

2)app.js核心程式碼

var getpostdata=require('./getpostdata')

router.post('/login',async(ctx)=>{
    var data=await getpostdata(ctx)
    console.log(data)//[Object: null prototype] { username: 'zhanghuan', password: '123' }
    ctx.response.body='<script>alert("success");history.back()</script>'
})

2外掛方式

1)安裝外掛

npm install koa-bodyparser --save

2)核心程式碼

var bodyparser=require('koa-bodyparser')//匯入

app.use(bodyparser())//配置,必須放在路由前面

router.post('/login',async(ctx)=>{
    console.log(ctx.request.body)//{ username: 'zhanghuan', password: '123' }
    ctx.response.body='<script>alert("success");history.back()</script>'
})

靜態web服務

1安裝

npm instaall koa-static --save

2核心程式碼

1)app.js

var static=require('koa-static')//匯入
app.use(static('./static'))//配置

2)html檔案中

<link rel="stylesheet" href="css/bootstrap.css">

art-template使用

1安裝

npm install art-template --save
npm install koa-art-template --save

2核心程式碼

var render=require('koa-art-template')
var path=require('path')

render(app, {
    root: path.join(__dirname, 'views'),   // 檢視的位置
    extname: '.ejs',  // 字尾名
    debug: process.env.NODE_ENV !== 'production'  //是否開啟除錯模式
});

router.get('/login',async(ctx)=>{
    await ctx.render('login',{'title':'title'})
})

3語法

{% raw %}
<!--引入-->
<%- include('header') -%>
    
<!--變數-->
{{name}}

<!--變數-->
{{name}}
    
<!--變數解析為html-->
{{@html}}
    
<!--判斷-->
{{if age>20}}
<p>age大於20</p>
{{else}}
<p>age小於等於20</p>
{{/if}}
   
<!--迴圈-->
<ul>
	{{each list}}
	<li>{{$index}}--{{$value}}</li>
	{{/each}}
</ul>
{% endraw %}

cookies的使用

1)設定

let options={
        maxAge:"1000*60",       //cookie有效時長,單位:毫秒數
        expires:"0000000000",      //過期時間,unix時間戳
        path:"/",         //cookie儲存路徑, 預設是'/,set時更改,get時同時修改,不然會儲存不上,服務同時也獲取不到
        domain:".xxx.com",       //cookie可用域名,“.”開頭支援頂級域名下的所有子域名
        secure:"false",       //預設false,設定成true表示只有https可以訪問
        httpOnly:"true",     //true,客戶端不可讀取
        overwrite:"true"    //一個布林值,表示是否覆蓋以前設定的同名的 cookie (預設是 false). 如果是 true, 在同一個請求中設定相同名稱的所有 Cookie(不管路徑或域)是否在設定此Cookie 時從 Set-Cookie 標頭中過濾掉。
    }
ctx.cookies.set('name','zhanghuan',options)

2)獲取

var name=ctx.cookies.get('name')

3)解決cookie無法用中文的問題

//設定cookies
router.get('/setcookies',async(ctx)=>{
    var str='今晚打老虎'
    var buffer=new Buffer(str).toString('base64')
    ctx.cookies.set('name',buffer,{maxAge:1000*60*60,})
    ctx.body="this is setcookies"
})

//獲取cookies
router.get('/getcookies',async(ctx)=>{
    var result=new Buffer(ctx.cookies.get('name'),'base64').toString()
    ctx.body="this is getcookies"
})

session使用

1安裝

npm install koa-session --save

2使用

var session=require('koa-session')

const CONFIG = {
    key: 'koa:sess',   //cookie key (default is koa:sess)
    maxAge: 86400000,  // cookie的過期時間 maxAge in ms (default is 1 days)
    overwrite: true,  //是否可以overwrite    (預設default true)
    httpOnly: true, //cookie是否只有伺服器端可以訪問 httpOnly or not (default true)
    signed: true,   //簽名預設true
    rolling: false,  //在每次請求時強行設定cookie,這將重置cookie過期時間(預設:false)
    renew: false,  //(boolean) renew session when session is nearly expired,
 };
 app.keys = ['some secret hurr'];//缺少這一行會報錯Error: .keys required for signed cookies
 app.use(session(CONFIG, app));

//設定session
router.get('/setsession',(ctx)=>{
    ctx.session.username='張歡'
    ctx.body='success'
})

//獲取session
router.get('/getsession',(ctx)=>{
    console.log(ctx.session.username)
    ctx.body=`${ctx.session.username}`
})

mongodb資料庫操作封裝

1config.js

//配置檔案
var app={
    dbUrl:'mongodb://localhost:27017',
    dbName:'db01'
}
module.exports=app

2db.js

//在此檔案內封裝資料庫操作的類
var mongoclient=require('mongodb').MongoClient
var ObjectID = require('mongodb').ObjectID
var config=require('./config.js')

class Db{
    static getIncetance(){//開啟單例模式
        if(!Db.incetance){
            Db.incetance=new Db()
        }
        return Db.incetance
    }
    constructor(){
        this.connect()
    }
    connect(){
        let _that=this
        return new Promise((resolve,reject)=>{
            if(!_that.dbClient){//解決重複連線問題
                mongoclient.connect(config.dbUrl,(err,client)=>{
                    if(err){
                        reject(err)
                        return
                    }else{
                        resolve(client.db(config.dbName))
                    }
                })
            }else{
                resolve(_that.dbClient)
            }
        })
    }
    find(collection,json={}){
        return new Promise(async(resolve,reject)=>{
            let db=await this.connect()
            let result=db.collection(collection).find(json)
            result.toArray((err,res)=>{
                if(err){
                    console.log(err)
                    reject(err)
                }else{
                    resolve(res)
                }  
            })
        })
    }
    update(collection,json1,json2){
        return new Promise(async(resolve,reject)=>{
            let db=await this.connect()
            db.collection(collection).updateOne(json1,{$set:json2},(err,data)=>{
                if(err){
                    console.log(err)
                    reject(err)
                }else{
                    resolve(data)
                }
            })
        })
    }
    delete(collection,json){
        return new Promise(async(resolve,reject)=>{
            let db=await this.connect()
            db.collection(collection).deleteOne(json,(err,data)=>{
                if(err){
                    console.log(err)
                    reject(err)
                }else{
                    resolve(data)
                }
            })
        })
    }
    insert(collection,json){
        return new Promise(async(resolve,reject)=>{
            let db=await this.connect()
            db.collection(collection).insertOne(json,(err,data)=>{
                if(err){
                    console.log(err)
                    reject(err)
                }else{
                    resolve(data)
                }
            })
        })
    }
    getObjectId(id){
        return new ObjectID(id)
    }
}

module.exports=Db.getIncetance()

3app.js

//封裝的類的使用案例
var koa=require('koa')
var router=require('koa-router')()
var db=require('./db.js')

var app=new koa()

app.use(router.routes())//配置路由
app.use(router.allowedMethods())

router.get('/',async(ctx)=>{//查詢
    let data=await db.find('user')
    //console.log(data)
    ctx.body=`共有${data.length}條資料`
})

router.get('/insert',async(ctx)=>{//新增
    let data=await db.insert('user',{'name':'王麻子','age':30,'sex':'male','job':'coder'})
    //console.log(data)
    ctx.body=`insert:${data}`
})

router.get('/delete',async(ctx)=>{//刪除
    let id=await db.getObjectId('5e4a88fc9ca5885c8806b955')//傳入字串為該條記錄的id,將其轉換成物件後再進行資料庫操作
    let data=await db.delete('user',{'_id':id})
    //console.log(data)
    ctx.body=`delete:${data}`
})

router.get('/update',async(ctx)=>{//更新
    let data=await db.update('user',{'name':'王麻子'},{'name':'王麻子11'})
    console.log(data)
    ctx.body=`update:${data}`
})

app.listen(3000)

路由模組化案例

實際開發中,各個模組需要進行分離

1分離思路

--package.json
--package-lock.json
--app.js//入口檔案
--views//存放html模板檔案
	--index.html
--static//存放靜態檔案
	--css
		--bootstrap.css
		--bootstrap.css.map
--routes//存放路由檔案
	--index.js
	--admin.js
--node_modules
--module//存放自定義模組

2檔案程式碼

1)app.js

var koa=require('koa')
var router=require('koa-router')()
var app=new koa()

//靜態路由
var static=require('koa-static')
app.use(static('./static'))

//路由
//業務流程均在路由裡
var router_index=require('./routes/index.js')/*前臺*/
var router_admin=require('./routes/admin.js')/*後臺*/
router.use('/',router_index)
router.use('/admin',router_admin)

//模板
//待渲染的html
var render=require('koa-art-template')
var path=require('path')
render(app,{
    root: path.join(__dirname, 'views'),   // 檢視的位置
    extname: '.html',  // 字尾名
    debug: process.env.NODE_ENV !== 'production'  //是否開啟除錯模式
})
app.use(router.routes())
app.use(router.allowedMethods())
app.listen(3000)
//此檔案是專案啟動的入口檔案

2)index.js

var router=require('koa-router')()

router.get('/',async(ctx)=>{
    ctx.render('index')
})

module.exports=router.routes()

3)admin.js

var router=require('koa-router')()

router.get('/',async(ctx)=>{
    ctx.body='這是admin管理頁面首頁'
})

module.exports=router.routes()

4)index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <link rel="stylesheet" href="/css/bootstrap.css">
</head>
<body>
    <h1>this is index</h1>
</body>
</html>

快速建立koa專案koa-generator

1全域性安裝

npm install koa-generator -g

2建立專案

koa koa-demo

3安裝依賴

cd ko-demo
npm install

4啟動專案

npm start

相關文章