美文网首页
前端框架系列之(mvc)

前端框架系列之(mvc)

作者: vv_小虫虫 | 来源:发表于2020-06-22 21:35 被阅读0次

前言

前面我们写了三篇关于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演示一下。

业务需求

  1. 接收用户输入的“用户名”和“密码”做登录操作
  2. 登录成功后返回“登录成功提示”

项目搭建

项目还是我们之前写的几篇文章使用的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我们确实定义了蛮多文件,比一般的开发方式复杂了不止一点,但是在一个多人合作的团队中怎么协调好每一个开发人员,这就需要一个很好的代码架构了,同样也是为了以后能够更好的迭代需求。

相关文章

网友评论

      本文标题:前端框架系列之(mvc)

      本文链接:https://www.haomeiwen.com/subject/ckoffktx.html