mvc三层架构
- mvc, 即 model 、controller、view;
- mvc模式将model、view、controller分离;使用mvc分层是系统更加灵活,扩展性更强。让程序更加直观、复用性更强、可维护性更强。
- model 负责数据访问;
- controller 负责消息处理;
- view 负责视图呈现。
利用mvc模式实现后端分层
- mvc分层开发模式: web server : 用户发起请求 => 分析用户请求,处理路由 => 处理数据(操作数据库,操作缓存)=> view(data+template)=> response。即 controller => model => view。
实现一个koa框架的web服务
const Koa = require('koa');
const KoaRouter = require('koa-router');
const KoaStaticCache = require('koa-static-cache');
const koaBody = require('koa-body');
const mainController = require('./contollers/main');
const userController = require('./contollers/user');
const itemController = require('./contollers/item');
const server = new Koa();
const router = new KoaRouter();
server.use( KoaStaticCache('./public', {
prefix: '/public',
gzip: true,
dynamic: true
}) );
server.use( koaBody({
multipart: true,
formidable: {
uploadDir: __dirname + '/public/upload',
keepExtensions: true
}
}));
router.get('/', mainController.index);
router.get('/user/register', userController.register);
router.get('/user/login', userController.login);
router.get('/item/add', itemController.add);
router.post('/item/add', itemController.addPost);
server.use( router.routes() );
server.listen(8081, () => {
console.log('服务启动成功:http://localhost:8081')
});
const tpl = require('../libs/tpl');
const itemsModel = require('../models/items');
module.exports = {
index: async ctx => {
let items = await itemsModel.getItems();
ctx.body = tpl.render('index.html', {
items
});
}
}
const tpl = require('../libs/tpl');
module.exports = {
register: async ctx => {
ctx.body = '注册';
},
login: async ctx => {
ctx.body = '登陆'
}
}
const tpl = require('../libs/tpl');
const categoriesModel = require('../models/categories');
const itemsModel = require('../models/items');
module.exports = {
add: async ctx => {
let categories = await categoriesModel.getCategories();
ctx.body = tpl.render('add-item.html', {
categories
});
},
addPost: async ctx => {
let data = ctx.request.body;
let files = ctx.request.files;
let filename = '';
if (files && files.cover) {
let lastPos = files.cover.path.lastIndexOf('/');
filename = files.cover.path.substring(lastPos+1);
}
let rs = await itemsModel.addItem([
data.category_id,
data.name,
data.price,
filename
]);
console.log('rs', rs);
ctx.body = '添加成功';
}
}
const nunjucks = require('nunjucks');
const tpl = new nunjucks.Environment(
new nunjucks.FileSystemLoader('views', {
watch: true,
noCache: true
})
);
module.exports = tpl;
const db = require('./model');
module.exports = {
getItems() {
return new Promise( (resolve, reject) => {
db.query("select * from `items`", function(err, rs) {
if (err) {
reject(err);
} else {
resolve(rs);
}
});
} )
},
addItem(newData) {
return new Promise( (resolve, reject) => {
db.query("insert into `items` (`category_id`, `name`, `price`, `cover`) values (?, ?, ?, ?)", newData, function(err, rs) {
if (err) {
reject(err);
} else {
resolve(rs);
}
});
} )
}
}
const db = require('./model');
module.exports = {
getCategories() {
return new Promise( (resolve, reject) => {
db.query("select * from `categories`", function(err, rs) {
if (err) {
reject(err);
} else {
resolve(rs);
}
});
} )
}
}
const mysql2 = require('mysql2');
let db = mysql2.createConnection({
host: '127.0.0.1',
port: 3306,
user: 'root',
password: 'Chen@123',
database: 'test'
});
module.exports = db;
<!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="/public/css/css.css" />
</head>
<body>
<div id="app">
<header id="header">
<a href="/" id="logo"></a>
<nav id="nav">
<a href="">1</a>
<a href="">笔记本</a>
<a href="">家居</a>
</nav>
<div id="user">
<a href="">登录</a>
<a href="">注册</a>
</div>
</header>
<div id="main">
<ul class="items-list">
{%for item in items%}
<li class="panel">
<img src="/public/upload/{{item.cover}}" alt="" class="cover">
<div class="name">{{item.name}}</div>
<div class="price">¥ {{(item.price / 100).toFixed(2)}}</div>
</li>
{%endfor%}
</ul>
<div class="pagination-container">
<div class="pagination">
<a href="" class="prev">上一页</a>
<a href="">1</a>
<a href="">2</a>
<a href="">3</a>
<a href="" class="current">4</a>
<a href="">5</a>
<a href="">6</a>
<a href="">7</a>
<a href="">8</a>
<a href="" class="next">下一页</a>
</div>
</div>
</div>
</div>
</body>
</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="/public/css/css.css" />
</head>
<body>
<header id="header">
<a href="/" id="logo"></a>
<nav id="nav">
<a href="">1</a>
<a href="">笔记本</a>
<a href="">家居</a>
</nav>
<div id="user">
<a href="">登录</a>
<a href="">注册</a>
</div>
</header>
<div id="main">
<div class="panel">
<h2>添加新商品</h2>
<form action="" method="post" enctype="multipart/form-data">
<div class="form-item">
<label>
<span class="txt">商品分类:</span>
<select name="category_id">
<option value="">请选择商品分类</option>
{%for category in categories%}
<option value="{{category.id}}">{{category.name}}</option>
{%endfor%}
</select>
</label>
</div>
<div class="form-item">
<label>
<span class="txt">商品名称:</span>
<input type="text" class="form-input" name="name">
</label>
</div>
<div class="form-item">
<label>
<span class="txt">价格:</span>
<input type="text" class="form-input" name="price">
</label>
</div>
<div class="form-item">
<label>
<span class="txt">封面:</span>
<input type="file" name="cover" />
</label>
</div>
<div class="form-item">
<label>
<span class="txt"></span>
<button class="form-button primary">确认添加</button>
</label>
</div>
</form>
</div>
</div>
</body>
</html>