浅析MVC

一 MVC

  • 定义

MVC全名Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写。使用MVC的目的是将M和V的实现代码分离,从而使同一个程序可以使用不同的表现形式。其中,View的定义比较清晰,就是用户界面。

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

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

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

typicalMVC.png

通过下面的的小栗子我们来简单认识一下MVC
数据层的代码放到M

const m = {
  data: {
    n: parseInt(localStorage.getItem("n"))
  },
  create() {},
  delete() {},
  update(data) {
    Object.assign(m.data, data); 
    eventBus.trigger("m:updated");
    localStorage.setItem('n', m.data.n);
  },
  get() {},
};
复制代码

视图层放到V

const v = {
  el: null,
  //第一次渲染html
  html: `
      <div>
        <div class="output">
          <span id="number">{{n}}</span>
        </div>
        <div class="actions">
          <button id="add1">+1</button>
          <button id="subtract1">-1</button>
          <button id="multiply1">*2</button>
          <button id="divide1">÷2</button>
        </div>
      </div>`,
  init(container) {
    v.el = $(container);
    v.render();
    console.log(v.render())
  },
  render(n) {
    if (v.el.children.length !== 0) v.el.empty();
    console.log(n)
    $(v.html.replace("{{n}}", n)).appendTo(v.el);
  },
};
复制代码

其他为C

const c = {
  init(container) {
    v.init(container);
    v.render(m.data.n); //view=render(data)  
    c.autoBindEvents();
    eventBus.on("m:updated", () => {
      v.render(m.data.n);
    });
  },
  events: {
    "click #add1": "add",
    "click #subtract1": "subtract",
    "click #multiply1": "multiply",
    "click #divide1": "divide",
  },
  add() {
    m.update({ n: m.data.n + 1 });
  },
  subtract() {
    console.log("here");
    m.update({ n: m.data.n - 1 });
  },
  multiply() {
    console.log("here");
    m.update({ n: m.data.n * 2 });
  },
  divide() {
    m.update({ n: m.data.n / 2 });
  },
  autoBindEvents() {
    for (let key in c.events) {
      const value = c[c.events[key]];
      const spaceIndex = key.indexOf(" ");
      const part1 = key.slice(0, spaceIndex);
      const part2 = key.slice(spaceIndex + 1);
      v.el.on(part1, part2, value);
    }
  },
};
复制代码

EventBus

主要有三个API:

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

示例:

const eventBus = $(window) 
const m = {
  data: {
    ...
  },
  update(data) {
    eventBus.trigger('m:updated')
  }
}

const v = {
  render(data) {
    ...更新数据
  }
}  
  
const c = {
  eventBus.on('m:updated', () => {
    v.render(m.data.n)
  })
}
复制代码

表驱动编程

表驱动方法是一种使你可以在表中查找信息,而不必用逻辑语句(if 或 case)来把他们找出来的方法。事实上,任何信息都可以通过表来挑选。在简单的情况下,逻辑语句往往更简单而且更直接。但随着逻辑链的复杂,表就变得越来越富于吸引力了。

表驱动编程的意义在于逻辑与数据的分离。(类似于事件委托)

例如:if-else

function translate(term) {
    if (term === '1') {
        return '一'
    } else if (term === '2') {
        return '二'
    } else if (term === '3') {
        return '三'
    } else {
        return '???'  
    }
}

// 如果想添加一个新的名词翻译,需要再添加一个if-else逻辑,例如:
function translate(term) {
    if (term === '1') {
        return '一'
    } else if (term === '2') {
        return '二'
    } else if (term === '3') {
        return '三'
    } else if (term === '4') {   
        // 此处添加了一个新的名词翻译
        return '四'
    } else {
        return '???'  
    }
}
复制代码

表驱动:

function translate(term) {
    let terms = {
        '1': '一',
        '2': '二',
        '3': '三'
    }
    return terms[term];
}

// 如果想添加一个新的名词翻译,只需要在terms中添加一个新的表项,不需要修改整个逻辑
function translate(term) {
    let terms = {
        '1': '一',
        '2': '二',
        '3': '三'
        '4': '四'   // 添加一个新的名词翻译
    }
    return terms[term];
}
复制代码

我是如何理解模块化的

把一堆复杂的代码,通过各自的功能的不同封装成不同的模块,将他们单独抽离出来。降低代码耦合度,各个模块有更好的独立性。这样做可以解决项目中的全局变量污染的问题,使开发效率更高,方便代码复用和维护 。

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享