浅析 MVC

230 阅读2分钟

一、MVC 三个对象

  • M-Model(数据模型),负责操作所有数据
  • V-View(视图),负责所有UI界面
  • C-Controller(控制器)负责其他

举例如下:

const m = {
  data: {
    index: 0,
    n: 0
  }
}

const v = {
  template: `
    <div>
      <span>姓名</span>
      <input type="text">
    </div>
  `
}

const c = {
  init() {

  }
}

二、EventBus

eventBus 的作用主要是用来实现对象之间的通信,例如我们可以通过 eventBus 来实现 M、V、C 三个对象之间的通信。

它有三个主要的API:

  • on 用于监听对象。
  • trigger 用于触发对象。
  • off 用于取消对象监听。

如在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)
  })
}

三、表驱动编程

表驱动方法是一种使你可以在表中查找信息,而不必用逻辑语句(ifcase)来把他们找出来的方法。这里的表指的是哈希表,它的核心就在于通过哈希表的形式把重复的代码进行剥离。表驱动编程的意义在于逻辑与数据的分离。

如下面的代码:

// jQuery 风格写法
$('#el1').on('事件A', fn1)
$('#el2').on('事件B', fn2)
$('#el3').on('事件C', fn3)
$('#el4').on('事件D', fn4)
$('#el5').on('事件E', fn5)

上述代码其实在做同一件事,通过一个元素("#el1等")执行某个事件("事件A等")从而达到某个目的("fn1等")。那么这样的代码是可以被优化为表结构的:

const evevts = {
  "#el1 事件A": "fn1",
  "#el2 事件B": "fn2",
  "#el3 事件C": "fn3",
  "#el4 事件D": "fn4",
  "#el5 事件E": "fn5"
}

const eventFunctions = {
  fn1: function() {},
  fn2: function() {},
  fn3: function() {},
  fn4: function() {},
  fn5: function() {}
}

// 通过一个公共的函数即可实现所有事件的调用
function autoBindEvents() {
  for(let key in events) {
    const spaceIndex = key.indexOf(' ')
    const el = key.splice(0, spaceIndex) // 获取元素
    const event = key.splice(spaceIndex+1) // 获取元素需要执行的事件
    const fn = eventFunctions[events[key]] // 执行事件后的函数
    $(el).on(event, fn)
  }
}

初看似乎代码变得更复杂了,但是当事件变多,我们就能发现它的优点:

  • 减少了重复的代码。

  • 增加了可扩展性,如:我们想为 #el2 换一个事件时执行操作 events 即可。

  • 降低逻辑复杂度,把需要 DOM 操作的地方变换为对一个数据表格的操作。

四、模块化

代码采用模块化后,可以做到互不影响 ,可以使得代码更加清晰、有利于分工和维护。

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

// 文件名name.js
const name = 'Jacky'
export {
    name
}
// index.js
import { name } from './name.js'
console.log(name) // "jacky"