浅析 MVC

103 阅读3分钟

什么是MVC

每个模块都可以写成三个对象,分别是M、V、C

M-Model(数据模型)负责操作所有数据

模型model用于封装与应用程序的业务逻辑相关的数据以及对数据的处理方法,会有一个或多个视图监听此模型。一旦模型的数据发生变化,模型将通知有关的视图。

V-View(视图)负责所有UI界面

视图view是它在屏幕上的表示,描绘的是model的当前状态。当模型的数据发生变化,视图相应地得到刷新自己的机会。

C-CONtroller(控制器)负责其他

控制器controller定义用户界面对用户输入的响应方式,起到不同层面间的组织作用,用于控制应用程序的流程,它处理用户的行为和数据model上的改变。

1644484339.png

其中涉及两种设计模式:

  • view和model之间的观察者模式,view观察model,事先在此model上注册,以便view可以了解在数据model上发生的改变。
  • view和controller之间的策略模式

各个部分的伪代码实现

Model

const m = {
    data: { //需要操作的数据或信息 },
    create: { //增数据 },
    delete: { //删数据 },
    update(data) { //改数据
       Object.assign(m.data, data) //使用新数据替换旧数据
       eventBus.trigger('m:upate') // eventBus触发'm:update'信息, 通知View刷新 
    },
    get:{ //获取数据 } 
}

View

const v = {
    el: null,
    html: `<div>...</div>`,    //html上的内容
    init(container) {
        v.el = $(container)  //需要刷新的元素
    },
    render(){ //刷新页面 
    }
}

Controller

const c = {
   init(){
      v.init() // View初始化
      v.render() // 第一次渲染
      c.autoBindEvents() // 自动的事件绑定
      eventBus.on('m:update', () => { v.render() }) 
      // 当eventBus触发'm:update'时View刷新
   },
   events:{ 
    'click #add1':'add'
   //事件以哈希表方式记录 },
   method() {
      data = 改变后的新数据
      m.update(data)
   },
   autoBindEvents() { //自动绑定事件 }
}EventBus

EventBus

EventBus一般用到以下三个API:

  • on(eventName, fn):用于监听事件,eventName传事件名字, fn传执行函数
  • trigger(eventName, data):用于触发事件,eventName传事件名字,data传其他参数
  • off(eventName, fn):用于取消监听,eventName传事件名字,fn传解绑的函数

伪代码例子:

const fn=() => {}
eventBus.trigger("m:updated");//触发m:updated事件
eventBus.on("m:updated", fn);//监听m:updated事件,如果m:updated事件被触发,执行函数fn
eventBus.off("m:updated", fn);//事件m:updated解绑函数fn,如果m:updated事件被触发,不再执行函数fn

什么是表驱动编程

表驱动法是一种编程模式,从表(哈希表)里面查找信息而不是使用逻辑语句(if…else…switch等),可以减少重复代码,只将重要的信息放在表里,然后利用表来编程,与逻辑语句相比较有着更稳定的复杂度。

如:下面这段代码重复率很高

bindEvents(){
  v.el.on('click', '#add1', () => {
    m.data.n += 1
    v.render(m.data.n)
  })
  v.el.on('click', '#minus1', () => {
    m.data.n -= 1
    v.render(m.data.n)
  })
}

当我们使用表驱动法后,可写为

events: {
  'click #add1' : 'add',
  'click #minus1' : 'minus'
},
add() {
  m.update( data: {n: m.data.n +1})
},
minus() {
  m.update( data: {n: m.data.n -1})
}

我是如何理解模块化的

  • 我的理解是将一个较复杂的项目文件,将这个文件中的各个部分或功能分割成各个模块(文件)去开发实现,这使得模块可以独立开发,在工作中,不同的模块也就可以交由不同的开发人员。
  • 而且在开发中我们也会用到一些共同API,这个时候我们也可以把这些抽离成一个公用模块,当需要引用这个函数或者功能的时候,只需要在相应的模块里面用import导入相应的包。
  • 使用模块化编程可以便于我们对该项目的后续维护和修改,不需要从大量的代码中寻找所需维护和修改的部分,能精准地找到我们所需维护或修改的模块,以及各个模块互不干扰,分开实现,不会因为某一个部分的出错,而影响到其他部分。而且模块化可以降低代码耦合度,减少重复代码,提高代码利用率。