快速上手、路由、動態路由、獲取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資料庫操作封裝
1
config.js
//配置檔案
var app={
dbUrl:'mongodb://localhost:27017',
dbName:'db01'
}
module.exports=app
2
db.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()
3
app.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