目录
- MVC的概念
- mvc的组成
- 项目中使用mvc进行优化
一、 MVC 简介
1.1 为什么要用mvc
- 在生活中,我们用衣柜存储服饰物品,但是如果一股脑全放进去,不加整理和归纳,后续的维护和使用就非常麻烦,所以推荐需要对物品进行整理和归纳。如图1 和图2
图1
图2
- 在后端编程中,
routes/路由.js就包含了路由的业务代码以及数据库的集合模型(Schema和关联)代码,整个文件包含了太多的内容,不方便后续维护。所以可以使用mvc模式对后端代码进行拆分,把不同作用的的代码放在不同的js文件中,对后续代码的维护和扩展更有帮助。
1.2 MVC 概念
-
MVC是一种软件的架构思想。主要是指规范了一个拥有良好扩展性、维护性的程序应该包含哪些部分。
-
MVC的主要内容:一个程序应该由三个部分组成
- M:model(模型):指的是程序处理的数据部分
- C:Controller(控制器):指的程序的业务代码
- V:view(视图):展示程序输出的部分。
-
MVC是通用的程序架构思想,不局限于后端项目,也同样适用其他语言编写的程序。
1.3 MVC在后端项目中的体现
-
目的:将后端Express项目的书写代码和mvc进行关联
-
组成
- M:模型(model):指的集合模型相关代码(Schema以及关联部分),并暴露关联集合生成的集合对象
- C:控制器(Controller):指的是具体处理数据的业务代码(登录、注册、删除、修改)
- V:视图(view): 指的是路由匹配的部分。指当哪个前端url对应哪个业务代码。
-
文件划分
-
mvc三个部分的代码都是放在不同的文件中,并且都有文件夹放置。按照mvc模式,可以将程序代码主要划分为三个文件及:
- models:包含所有集合的模型相关代码,每个集合也是一个独立的js文件
- controllers:包含所有处理前端数据的业务代码,每一类数据的处理代码都是放在该文件夹下独立的一个js文件
- routes:包含了所有的路由js文件,里面仅仅包含了路由地址和业务代码的匹配部分(需引入控制器的js文件)
-
例子: 蜗牛电影系统
moviesystem10 --- models --- userModel.js --- movieModel.js --- movieTypeModel.js --- actorModel.js --- comtrollers --- userController.js --- movieController.js --- actorController.js --- routes --- movieRoute.js --- userRoute.js --- movieTypeRoute.js --- actorRoute.js
-
二、MVC例子:movieType.js
2.1 MVC优化之前
-
一个
/routes/movieType.js就包含了集合模型代码、业务代码以及路由匹配在内的所有代码var express = require(‘express’); var router = express.Router(); const mongoose = require(‘mongoose’); const movieTypesSchema = new mongoose.Schema({ //_id是自动引入并转换name:String },{ //取消_v字段生成versionKey:false }) let movieTypesModel = mongoose.model(“movieTypesModel”,movieTypesSchema,’movieTypes’); //查找所有 router.get(‘/findall’,async function(req, res, next) { let result = await movieTypesModel.find(); res.send({code:200,message:’查询成功’,data:result}) }); //模糊查询 router.get(‘/find’,async function(req, res, next) { let {name} = req.query;let result = await movieTypesModel.find({ name:{$regex:new RegExp(name),$options:"$i"}}); res.send({code:200,message:'查询成功',data:result})}); //添加 router.get(‘/add’,async function(req, res, next) { let {name} = req.query;//先尝试能不能查找到数据,如果查到了,说明已经有该电影类型了 let result = await movieTypesModel.find({name});if(result.length > 0){ res.send({code:200,message:'添加失败,已有该类型'})}else{ let end = await movieTypesModel.create({name}); res.send({code:200,message:'添加成功'})} }); // 删除 router.get(‘/delete’,async function(req, res, next) { let {_id} = req.query;let {deletedCount} = await movieTypesModel.deleteMany({_id});if(deletedCount > 0){ res.send({code:200,message:'删除成功'})}else{ res.send({code:200,message:'删除失败'})} }); //修改名称:根据_id来查找 router.get(‘/update’,async function(req, res, next) { let {_id,name} = req.query;//先确定要修改的名称是否已存在,已存在则修改失败 let arr = await movieTypesModel.find({name});if(arr.length >0 ){ res.send({code:200,message:'修改失败,已有该类型'}); return;}let {modifiedCount} = await movieTypesModel.updateMany({_id},{name});if(modifiedCount > 0){ res.send({code:200,message:'修改成功'})}else{ res.send({code:200,message:'修改失败'})} }); //分页查询 router.get(“/findByPage”,async function(req,res){ try { let {pageNum,pageSize} = req.query;//分页查询// 跳过的数量; (pageNum - 1) * pageSize let result = await movieTypesModel.find().skip((pageNum - 1) * pageSize).limit(pageSize); res.send({code:200,message:'分页查询成功',data:result})} catch (error) { console.log('报错来源',error); //告诉用户参数有问题 res.send({code:-1,message:'分页查询失败,参数有误'})} }) //测试 skip limit Documentcount router.get(‘/find2’,async function(req,res){ //skip// let result = await movieTypesModel.find().skip(5)//limit 获取前三个数据// let result = await movieTypesModel.find().limit(3);//返回第二到第五个数据// let result = await movieTypesModel.find().skip(2).limit(2);//查看该集合数据的个数 let result = await movieTypesModel.countDocuments()res.send({code:200,message:'查询成功',data:result}) module.exports = router; ### 2.2 MVC优化之后- 需要再`models`、`controllers`以及`routes`新建三个文件 - `models/movieType.js`:包含电影类型的集合模型代码 - `controllers/movieTypeController.js`:包含了处理电影类型的所有业务代码 - `routes/movieTypeRoute.js`:包含了电影类型的所有路由匹配代码- 1.models/movieType.js: ```js const mongoose = require('mongoose'); const movieTypesSchema = new mongoose.Schema({ //_id是自动引入并转换 name:String },{ //取消_v字段生成 versionKey:false }) //需要暴露生成的集合对象 let movieTypesModel = mongoose.model("movieTypesModel",movieTypesSchema,'movieTypes'); //暴露movieTypesModel module.exports = movieTypesModel
-
2.
controllers/movieTypeController.js: const movieTypesModel = require("../models/movieTypeModel"); //查询所有 async function findAll (req, res, next) { let result = await movieTypesModel.find(); res.send({code:200,message:'查询成功',data:result}) } //模糊查询 async function find(req, res, next) { let {name} = req.query; let result = await movieTypesModel.find({ name:{$regex:new RegExp(name),$options:"$i"} }); res.send({code:200,message:'查询成功',data:result}) } // 添加 async function add(req, res, next) { let {name} = req.query; //先尝试能不能查找到数据,如果查到了,说明已经有该电影类型了 let result = await movieTypesModel.find({name}); if(result.length > 0){ res.send({code:200,message:'添加失败,已有该类型'}) }else{ let end = await movieTypesModel.create({name}); res.send({code:200,message:'添加成功'}) } } //修改 async function update(req, res, next) { let {_id,name} = req.query; //先确定要修改的名称是否已存在,已存在则修改失败 let arr = await movieTypesModel.find({name}); if(arr.length >0 ){ res.send({code:200,message:'修改失败,已有该类型'}); return; } let {modifiedCount} = await movieTypesModel.updateMany({_id},{name}); if(modifiedCount > 0){ res.send({code:200,message:'修改成功'}) }else{ res.send({code:200,message:'修改失败'}) } } //分页查询 async function findByPage(req,res){ try { let {pageNum,pageSize} = req.query; //分页查询 // 跳过的数量; (pageNum - 1) * pageSize let result = await movieTypesModel.find().skip((pageNum - 1) * pageSize).limit(pageSize); res.send({code:200,message:'分页查询成功',data:result}) } catch (error) { console.log('报错来源',error); //告诉用户参数有问题 res.send({code:-1,message:'分页查询失败,参数有误'}) } } //删除 async function deleteType(req, res, next) { let {_id} = req.query; let {deletedCount} = await movieTypesModel.deleteMany({_id}); if(deletedCount > 0){ res.send({code:200,message:'删除成功'}) }else{ res.send({code:200,message:'删除失败'}) } } //暴露所有函数 module.exports ={ find, findAll, findByPage, update, add, deleteType }- 包含了处理数据的所有函数,并暴露所有函数
-
/routes/movieRoute.js:包含路由地址匹配代码var express = require("express"); var router = express.Router(); //引入控制器代码:业务代码 const { find, findAll, findByPage, deleteType, add, update, } = require("../controllers/movieTypeController"); //查找所有 router.get("/findall", findAll); //模糊查询 router.get("/find", find); //添加 router.get("/add", add); // 删除 router.get("/delete", deleteType); //修改名称:根据_id来查找 router.get("/update", update); //分页查询 router.get("/findByPage", findByPage); module.exports = router;