浅析 MVC

307 阅读3分钟

一、 MVC 是什么

模型 Model:负责操作所有的数据。

视图 View: 负责所有 UI 界面。

控制器 Controller:负责其他。

MVC 是一种架构设计模式,包括三类对象,将它们分离以提高灵活性和复用性。它们相互之间可以通信。

image.png 经典 MVC 模式中:

  • Model 用于封装与业务逻辑相关的数据以及处理方法,会有一个或多个视图监听此模型,一旦模型的数据发生变化,模型将通知有关的视图。
  • View 是它在用户屏幕上的显示,描绘的是 Model 当前的状态。当模型的数据发生变化,视图相应的得到刷新自己的机会。
  • Controller 处理用户的行为和数据上的改变,控制流程,起到不同层面间的组织作用。

Model 的伪代码实现

Model = {
    data: { 程序需要操作的数据或信息 },
    creat: { 增数据 },
    delete: { 删数据 },
    get: { 获取数据 },
    update: { 更新数据的方法:使用新数据替换旧数据,通知 View 刷新 }
}

View 的伪代码实现

View = {
    el: 需要刷新的元素,
    html: `需要展示在页面上的内容,字符串`,
    init: { 初始化 },
    render: { 渲染 }
}

Controller 的伪代码实现

Controller = {
    events: { 哈希表记录重要事件 },
    autoBindEvents { 自动绑定事件 },
    method: { 更新数据 }
}

二、EventBus

JS 中的 EventBus(事件总线)的核心思想就是:发布订阅者模式。JS 中基本上所有的事件都是采用的这种发布订阅者模式,如clickmousemove等。

原理图如下:

image.png

EventBus 常用API的简易实现

class EventBus {
  constructor() {
    // 定义一个总事件对象,每一个 key 就是一个事件,value 就是触发该事件时所有的回调
    this.eventList = {
      // 'event1':[cb1, cb2, cb...],
      // 'event2':[cb1, cb2, cb...],
    };
  }

  /*
  * $on 添加 event 对应的 callback
  * @param {[String]}  event [事件名称]
  * @param {[Function]}  callback [触发事件执行的回调]
  * */
  $on(event, callback) {
    let eventList = this.eventList[event];
    // 调用 $on 的时候,将 callback 推入对应 event 的数组中
    eventList ? eventList.push(callback) : this.eventList[event] = [callback];
  }

  /*
  * $emit 触发某个 event,执行对应的所有 callback 函数
  * @param {[String]}  event [事件名称]
  * @param {[Any]}  params [执行回调时传入的参数]
  * */
  $emit(event, [params]) {
    let eventList = this.eventList[event];
    if (!eventList) return;
    eventList.forEach(fn => {
      fn.apply(this, params);
    });
  }

  /*
  * $off 删除 event
  * @param {[String]}  event [事件名称]
  * @param {[Function]}  callback [事件函数]
  * */
  $off(event, callback) {
    let eventList = this.eventList[event];
    if (callback) {
      let index = eventList[event].indexOf(callback);
      eventList[event].splice(index, 1);
    } else {
      eventList[event].length = 0;
    }
  }
}

三、表驱动编程

表驱动编程即从表里面查找信息,而不使用逻辑语句(如if、case)。事实上,凡是能通过逻辑语句来选择的事物,都可以通过查表来选择。

这样的好处在简单的情况下不太看得出来,但随着逻辑链越来越长的话,如果使用if...else...这样的语句,我们的代码量是成线性增长的。

使用哈希表来记录这些映射关系的话,就可以让我们的数据部分和代码部分分离,实现稳定的简单。

const list = {
    "Sam":20,
    "Jack":23,
    "Amy":18,
    ...
}
function age(name) {
    name in list ? console.log(name + "的年龄是" + list[name]) : console.log("查无此人")
}

四、我理解的模块化编程

模块化使得整个系统的结构变得更加清晰、容易理解,当我们将系统分离成独立功能的模块后,我们需要什么功能,就加载什么功能。这样不仅防止了作用域冲突,有利于人们的排错,而且提升代码的可复用性和可维护性。 ES6 中新增的两个关键字:exportimport就是一个模块化的解决方案,export用于把模块里的内容暴露给外部,import用于引入模块。