前言
前面我们写了三篇关于es装饰器的文章了,感兴趣的可以去看看:
简介
MVC 是一种使用 MVC(Model View Controller 模型-视图-控制器)设计创建 Web 应用程序的模式:
- Model(模型)表示应用程序核心(比如数据库记录列表)。
- View(视图)显示数据(数据库记录)。
- Controller(控制器)处理输入(写入数据库记录)。
MVC 模式同时提供了对 HTML、CSS 和 JavaScript 的完全控制。
Model(模型)是应用程序中用于处理应用程序数据逻辑的部分。
通常模型对象负责在数据库中存取数据。
View(视图)是应用程序中处理数据显示的部分。
通常视图是依据模型数据创建的。
Controller(控制器)是应用程序中处理用户交互的部分。
通常控制器负责从视图读取数据,控制用户输入,并向模型发送数据。
MVC 分层有助于管理复杂的应用程序,因为您可以在一个时间内专门关注一个方面。例如,您可以在不依赖业务逻辑的情况下专注于视图设计。同时也让应用程序的测试更加容易。
MVC 分层同时也简化了分组开发。不同的开发人员可同时开发视图、控制器逻辑和业务逻辑。
网上有很多对它的描述,比如:
在这里插入图片描述在这里插入图片描述
网上一搜你会发现有很多种表达方式,那到底哪些是对的呢?其实都是对的。为什么这么说呢,这得从mvc的发展说起。
MVC框架模式最早由Trygve Reenskaug 于1978年在Smalltalk-80系统上首次提出。经过了这么多年的发展,当然会演变出不同的版本,但核心没变依旧还是三层模型Model-View-Control。
下面我们用常见的业务需求结合代码做一个demo演示一下。
业务需求
- 接收用户输入的“用户名”和“密码”做登录操作
- 登录成功后返回“登录成功提示”
项目搭建
项目还是我们之前写的几篇文章使用的demo项目vue+typescript
代码已经上传到github了,小伙伴自己去clone一份就可以了https://github.com/913453448/vue-property-decorator-demo
在这里插入图片描述需求实现
src下面直接创建一个mvc目录,然后把main.ts入口文件中的组件指向mcv/index.vue。
import Vue from "vue";
import Demo from "./mvc/index.vue";
new Vue({
render(h){
return h(Demo);
}
}).$mount("#app");
Model
model在我们需求可以看成是user的数据持久化层,但是在前端的话,我们可以看成是利用网络协议去后端获取数据操作。
首先我们创建一个叫User的实体类用来传递和保存用户信息:
export default class User {
id!: string;
name!: string;
pwd!: string;
}
然后我们定义一个叫IUserModel.ts的接口文件。
IUserModel.ts
import User from "./User";
/**
* user数据持久化接口层
*/
export default interface IUserModel {
/**
* 用户登录
* @param {string} name
* @param {string} pwd
* @returns {Promise<User>}
*/
login(name: string, pwd: string): Promise<User>
}
可以看到,里面定义了一个叫login的方法,然后以一个promise的方式返回了一个User对象。
接口定义好了,现在我们来定义一下具体的model的实现类UserModelImp.ts。
UserModelImp.ts
import User from "./User";
import IUserModel from "./IUserModel";
/**
* user数据持久化实现层
*/
export default class UserModelImp implements IUserModel {
/**
* 用户登录
* @param {string} name
* @param {string} pwd
* @returns {Promise<User>}
*/
login(name: string, pwd: string): Promise<User> {
return new Promise((resolve, reject) => {
if ("123456" === pwd) {
const user = new User();
user.id = "1000";
user.name = name;
user.pwd = pwd;
resolve(user);
} else {
reject(new Error("密码错误"));
}
});
}
};
在这里我们模拟了一下前台跟后台的交互逻辑,然后直接返回user跟错误了,代码很简单,我就不一行行解析了。
Controller:
controller负责跟view的交互操作,然后通知对应的model去处理相应的逻辑,最后把结果返回给view。
我们先定义一个controller接口.
IUserController.ts
/**
* user控制器接口
*/
import User from "./User";
export default interface IUserController {
/**
* 用户登录
* @param {string} name
* @param {string} pwd
*/
login(name: string, pwd: string): Promise<User>;
}
IUserController.ts的具体实现类。
IUserController.ts
import IUserController from "./IUserController";
import UserModelImp from "./UserModelImp";
import User from "./User";
/**
* user逻辑处理层
*/
export default class UserControllerImp implements IUserController {
private userModel = new UserModelImp();
login(name: string, pwd: string): Promise<User> {
return this.userModel.login(name, pwd);
}
}
可以看到,我们创建了一个UserModelImp(用户逻辑处理类),然后直接调用了UserModelImp的login方法。
View:
view在我们项目也就是我们的index.vue文件,我们接收用户的输入,然后响应用户的点击事件。
同样的,我们创建一个接口IUserView.ts
IUserView.ts
/**
* user view接口
*/
import UserControllerImp from "./UserControllerImp";
export default interface IUserView {
/**
* 用户逻辑控制层
*/
userViewImp: UserControllerImp;
/**
* 登录响应
*/
onLogin(): void;
/**
* 展示消息
* @param {string} msg
*/
showMessage(msg: string): void;
}
然后是具体的实现类index.vue
index.vue
<template>
<div>
用户名:<input name="name" v-model="name"><br>
密码:<input name="pwd" v-model="pwd"><br>
<button @click="onLogin">登录</button>
</div>
</template>
<script lang="ts">
import Vue from "vue";
import Component from "../view/component";
import UserControllerImp from "./UserControllerImp";
import IUserView from "./IUserView";
@Component
class UserViewImp extends Vue implements IUserView{
userViewImp: UserControllerImp; //用户逻辑控制层
name = ""; //用户名
pwd = ""; //密码
constructor() {
super();
this.userViewImp = new UserControllerImp();
}
/**
* 去登录
*/
onLogin() {
this.userViewImp.login(this.name, this.pwd)
.then((user) => {
this.showMessage("欢迎你:" + user.name);
}).catch((error) => {
this.showMessage("登录失败-->" + error.message);
});
}
/**
* 展示消息
* @param {string} msg
*/
showMessage(msg = "") {
alert(msg);
}
}
export default UserViewImp;
</script>
编译运行
npm run dev
运行结果
在这里插入图片描述在这里插入图片描述
总结
-
具有一定的分层,代码层次比较分明,model层彻底解耦了
-
业务逻辑放在了model层,使得model的扩展性和灵活性变强了
-
controller跟view并没有完全的解耦
哈哈,mvc我们分析完毕了,有小伙伴就要说了:“你这不是在搞事情吗?定义那么多文件,又是接口又是实现类的,太麻烦啦!”
是的! 为了实现mvc我们确实定义了蛮多文件,比一般的开发方式复杂了不止一点,但是在一个多人合作的团队中怎么协调好每一个开发人员,这就需要一个很好的代码架构了,同样也是为了以后能够更好的迭代需求。
网友评论