Koa搭建一个后台系统

前面用exprss搭建了一个简单的后台管理系统,现在用koa来的搭建一个同样的后台系统,除了基本语法稍有不同外,其实大部分思路是一样的,话不多说,上代码
准备工作:
为了检测代码改变,安装一个nodemon

cnpm  install nodemon -D
//在package.josn添加配置
"scripts": {
    "start": "nodemon app.js",
    "test": "echo \"Error: no test specified\" && exit 1"
  },

好了:开干
1:安装koa

cnpm  install koa -D

2:安装koa-router

const  router = require('koa-router')();

3:初始化一个koa

const app = new  koa();

4:添加一个配置,启动路由,重要很容易漏掉的哦

app.use(router.routes());   /*启动路由*/
app.use(router.allowedMethods());
app.listen('3333',()=>console.log('server  init'));

这样一个基本的koa服务就搭建完成了,下面来讲解模板引擎的使用
express中我们使用了ejs,现在用一个比ejs性能更好的模板koa-art-template。
上代码
1:安装koa-art-template(https://www.npmjs.com/
不会的可以上去npm查看)

cnpm  install koa-art-template

2:引入使用

const  render = require('koa-art-template');
//配置模板引擎
render(app, {
    root: path.join(__dirname, 'views'),
    extname: '.html',
    debug: process.env.NODE_ENV !== 'production'
});

具体使用

router.get('/add',async (ctx)=>{

    await  ctx.render('admin/user/add');

})

image.png

ps:这里注意views不能修改文件名,后缀可以用我们熟悉的html
###添加一个static公共静态资源

//配置 静态资源的中间件
1:cnpm install koa-static -D
2:引入 const  static = require('koa-static');
3:使用 app.use(static(__dirname + '/public'));

接下来介绍一下session,方便用于用户登录判断、权限等一系列的使用哦

1:安装cnpm install koa-session -D
2:引入const  session = require('koa-session');
3:使用
//配置session的中间件
app.keys = ['some secret hurr'];
const CONFIG = {
    key: 'koa:sess',
    maxAge: 864000,
    overwrite: true,
    httpOnly: true,
    signed: true,
    rolling: true,   /*每次请求都重新设置session*/
    renew: false,
};
app.use(session(CONFIG, app));

####那么如何测试和使用了?
我们用一个登录页面模拟登录成功后写入session,然后后续访问其他页面,用这个来判断,有session才可以访问,没有就跳转到登录页面,进行登录判断才可以后续的操作
思路如下
1:登录页面
2:定义后台api接口,获取数据
3:在数据库查询匹配,成功就写入
4:路由跳转指定页面

好,开始
1:定义一个login.html页面
2:定义一个提交接口

<form action="{{__HOST__}}/admin/login/doLogin" method="post" id="loginForm">

ps:这里__host__,使用了一个全局变量定义
方法如下
定义一个全局中间件 ctx.state.__host__来实现的

//全局路由访问的中间件 
router.use(async (ctx,next)=>{
	//获取url的地址 设置http://localost:3333
	ctx.state.__HOST__='http://'+ ctx.request.header.host;
	//console.log(ctx.request.header.host);
	console.log('userinfo='+ctx.session.userinfo)
	//这里做权限控制   已经登录直接跳转后台首页 
	if(ctx.session.userinfo){
		await next();  //已经登录 继续向下执行
	}else{ //没有登录
		console.log(ctx.request.url);
		if(ctx.request.url =='/admin/login' || ctx.request.url =='/admin/login/doLogin'){   // 登录页面和登录接口向下执行
			await next();
		}else{  //判断不是登录页面和登录接口 就跳转必须去登录页面
			ctx.redirect('/admin/login');
			
		}
	}
	next();
});

好了现在来看登录接口提交

//post 提交
router.post('/doLogin',async (ctx)=>{
	
	console.log(ctx.request.body);
	//获取数据
	let username=ctx.request.body.username;
	
	let password=ctx.request.body.password;
	
	let code=ctx.request.body.code;
	
	//console.log(tools.md5(password));
	
	    //1、验证用户名密码是否合法
	
	    //2、去数据库匹配
	
	    //3、成功以后把用户信息写入sessoin
//	if(code.toLocaleLowerCase()==ctx.session.code.toLocaleLowerCase()){
	
	        //后台也要验证码用户名密码是否合法
	        var result=await DB.find('user',{"username":username,"pwd":tools.md5(password)});
			console.log('result'+result)
	        if(result.length>0){
	            //console.log('成功');
	            console.log(ctx.state.__HOST__);
				//成功后写入sessioon ,方便下次不用登录和判断用	
	            ctx.session.userinfo=result[0];
				console.log('session='+ ctx.session.userinfo);
				//路由重定向
	            ctx.redirect(ctx.state.__HOST__+'/admin');
	        }else{
	            //console.log('失败');
	            ctx.render('admin/error',{
	                message:'用户名或者密码错误',
	                redirect: ctx.state.__HOST__+'/admin/login'
	            })
	
	        }
	// }else{
	// 	ctx.render('admin/error',{
	// 		message:'验证码失败',
	// 		redirect: ctx.state.__HOST__+'/admin/login'
	// 	})
	// }
		
	await ctx.render('admin/login');
	
});

这里封装了mongoDb的增删改查,后续单独介绍

这里一个基本的koa-seesion就完成了。

接下来我们做些优化,如果一个一个路由全部放在app.js中,那么这个文件就太多了,后期不好维护,所以我们进行拆分为单独的文件
大概方案如下:
image.png
我们再来看看app.js中如何实现的

//引入路由模块
const  admin = require('./routes/admin')
const  api = require('./routes/api')
const  index = require('./routes/index')

router.use('/admin',admin);
router.use('/api',api);
//router.use(index);

ps:所以以/admin开头的全部访问admin这个js,也就是引入的admin路由
admin.js

const  router = require('koa-router')();

const login =require('./admin/login');
const user =require('./admin/user');

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

router.use('/login',login);
router.use('/user',user);


module.exports=router.routes();

user.js

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

router.get('/',async (ctx)=>{
    await  ctx.render('admin/user/list');
})
router.get('/add',async (ctx)=>{
    await  ctx.render('admin/user/add');
})
router.get('/edit',async (ctx)=>{
    ctx.body="编辑用户";
})
router.get('/delete',async (ctx)=>{
    ctx.body="删除用户";
})
module.exports=router.routes();

这样路由就分开了,只需要单独找到特定模块,然后维护路由即可

下面介绍下数据库mongoDb的封装

1:定义配置信息

var app={
    dbUrl: 'mongodb://localhost:27017/',
    dbName: 'dongdong'
}
module.exports=app;

2:配置具体实现

//DB库
var MongoDB=require('mongodb');
var MongoClient =MongoDB.MongoClient;
const ObjectID = MongoDB.ObjectID;

var Config=require('./config.js');

class Db{

    static getInstance(){   /*1、单例  多次实例化实例不共享的问题*/

        if(!Db.instance){
            Db.instance=new Db();
        }
        return  Db.instance;
    }

    constructor(){

        this.dbClient=''; /*属性 放db对象*/
        this.connect();   /*实例化的时候就连接数据库*/

    }

    connect(){  /*连接数据库*/
      let _that=this;
      return new Promise((resolve,reject)=>{
          if(!_that.dbClient){         /*1、解决数据库多次连接的问题*/
              MongoClient.connect(Config.dbUrl,(err,client)=>{

                  if(err){
                      reject(err)

                  }else{

                      _that.dbClient=client.db(Config.dbName);
                      resolve(_that.dbClient)
                  }
              })

          }else{
              resolve(_that.dbClient);

          }


      })

    }

    find(collectionName,json){

       return new Promise((resolve,reject)=>{

            this.connect().then((db)=>{

                var result=db.collection(collectionName).find(json);

                result.toArray(function(err,docs){

                    if(err){
                        reject(err);
                        return;
                    }
                    resolve(docs);
                })

            })
        })
    }
    update(collectionName,json1,json2){
        return new Promise((resolve,reject)=>{

                this.connect().then((db)=>{

                    //db.user.update({},{$set:{}})
                    db.collection(collectionName).updateOne(json1,{
                        $set:json2
                    },(err,result)=>{
                        if(err){
                            reject(err);
                        }else{
                            resolve(result);
                        }
                    })

                })

        })

    }
    insert(collectionName,json){
        return new  Promise((resolve,reject)=>{
            this.connect().then((db)=>{

                db.collection(collectionName).insertOne(json,function(err,result){
                    if(err){
                        reject(err);
                    }else{

                        resolve(result);
                    }
                })


            })
        })
    }

    remove(collectionName,json){

        return new  Promise((resolve,reject)=>{
            this.connect().then((db)=>{

                db.collection(collectionName).removeOne(json,function(err,result){
                    if(err){
                        reject(err);
                    }else{

                        resolve(result);
                    }
                })


            })
        })
    }
    getObjectId(id){    /*mongodb里面查询 _id 把字符串转换成对象*/

        return new ObjectID(id);
    }
}


module.exports=Db.getInstance();

效果图
image.png

这里用到了单例模式,解决了数据库多次连接耗费时间的性能问题,第二次不需要初始化,直接使用,

    static getInstance(){   /*1、单例  多次实例化实例不共享的问题*/
        if(!Db.instance){
            Db.instance=new Db();
        }
        return  Db.instance;
    }

    constructor(){
        this.dbClient=''; /*属性 放db对象*/
        this.connect();   /*实例化的时候就连接数据库*/

    }

module.exports=Db.getInstance();

关键代码如下
image.png

亲测有效·········
最后上传一个效果图···
image.png

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值