浅浅谈一下MVC

208 阅读3分钟

MVC是啥

MVC是三个字母的首字母缩写,它们是Model(数据模型)、View(视图)、Controller(控制器)。 这个模式可以把每个模块(不论简单或复杂)分成三层:

  • 最上面的一层,是View(视图层),负责所有UI界面。
  • 最底下的一层, 是Model(数据层), 负责程序需要操作的数据或信息。
  • 中间的一层,是Controller(控制层),复杂其他业务逻辑。 这三层是紧密联系在一起的,但又是互相独立的,每一层内部的变化不影响其他层。每一层都对外提供接口(Interface),供上面一层调用。这样一来,软件就可以实现模块化,修改外观或者变更数据都不用修改其他层,大大方便了维护和升级。直接上代码(其实是伪代码lol):
// m用于保存数据,操作数据
const m={
    data:{n:1},
    create(){}, // 增
    delete(){}, // 删
    update(){}, // 改
    get(){} // 查
}
// v负责渲染页面相关
const v={
    el:null,  // 容器
    html:``,  // html代码
    render(data){}
}
// c负责其他部分,如初始化,获取元素,绑定事件等
const c={
    init(){}
    autoBindEvents(){}
    event:{}
}

EventBus又是啥

EventBus主要用于对象间通信,可以通过与jQuery合作封装一个window或者空对象,调用其提供的on、off、trigger等API,从而实现对象间数据传输和通信。

  • 举个栗子
import $ from "jquery";

var eventBus = $({});

eventBus.on("test:event", function (event, data) {
	console.log("Saw a test event: event=%o, data=%o", event, data);
});

eventBus.trigger("test:event", { test_data: "foo" });
  • 再举个栗子:如在MVC 中可以采用 eventBus来实现 M 层数据的变化自动触发 V 层的更新:
const eventBus = $(window) // 获取eventBus 对象
const m = {
  data: {
    ...
  },
  update(data) {
    // trigger 触发事件更新数据
    eventBus.trigger('m:updated')
  }
}

const v = {
  render(data) {
    ...更新数据
  }
}  
  
const c = {
  eventBus.on('m:updated', () => {
    // on方法执行监听后触发 v 的视图更新
    v.render(m.data.n)
  })
}
  • 同理,EventBus在Vue中,实质就是一个Vue对象,通过$on$off$emit等API进行组件间数据传输和通信。具体例子详见 Vue系列之:eventBus的的使用

表驱动编程又又是啥

表驱动模式是一种(scheme) -- 从表里查找信息而不使用逻辑语句(if 和 case)。

  • 如我们需要编写一个方法,用来获取每个月的天数,一般做法是
function GetDaysPerMonth(month) {
    if (month == 1) {
        return 31
    } else if (month == 2) {
        // 不考虑闰年
        return 28
    } else if (month == 3) {
        return 31
    } else if (month == 4) {
        return 30
    } else if (month == 5) {
        return 31
    }
    ....
}
  • 采用表驱动模式后,代码如下
// 使用哈希表来存储月份和天书的映射关系
const result = [31, 28, 31, 30, 31...]
function GetDaysPerMonth(month) {
    return result[month-1]
}
  • 使用表驱动编程模式的进行改成本质上就是使用一个哈希表/数组来存储条件和结果的映射关系。

如何理解模块化

如果没有模块化时,我们可能会按如下方式划分模块:
通过 <script> 标签引入各个文件,把每个文件看成是一个模块,每个模块的接口通常是暴露在全局作用域下的,也就是定义在 window 对象中。

<script src="module1.js"></script>
<script src="module2.js"></script>
<script src="module3.js"></script>

如果通过这种方式做模块化,当项目变得越来越大时,很容易造成全局变量冲突,项目也会变得越来越难以管理。
因此我们需要找到一种合适的方式来帮助我们模块化,模块化能给我们带来哪些好处呢?具体来说,主要包含以下几个方面:

  1. 减少全局变量污染
  2. 控制依赖
  3. 增强代码的可维护性
  4. 增加代码的复用性
  5. 分治思想的实践

JavaScript 主要通过 import 与 export 来进行模块化操作(详见MDN文档

参考阅读