今天我们来总结一下什么是MVC。
MVC是一种设计模式,当我们在编写JavaScript代码时,往往会因为封装不足或者需求过多而产生一篇又长又臭的代码,为了解决代码重复、页面重复的问题,我们可以使用MVC设计模式来进行代码重构。
MVC定义
MVC包括三大类对象,但是它们的定义并不是一成不变的,在不同的程序员眼中MVC所涵盖的内容不一定相同,这里只是列举我个人的看法和一些伪代码的例子:
M:model,即数据模型,我们可以将页面中所有操作数据的代码整合在M模块中以用来操作数据,一旦模型的数据发生变化,模型应当通知有关视图;
const m = {
//初始化数据
data: {
n: parseInt(localStorage.getItem('n'))
},
create() { },
delete() { },
update(data) {
Object.assign(m.data, data); //把data所有的属性一个个赋值给m的data
eventBus.trigger('m:updated')
localStorage.setItem('n', m.data.n)
},
get() { }
}
V:view,即视图,负责所有UI界面的代码应该整合在V模块中,描述了model模块当前的状态,当数据发生变化时,视图应该获得刷新的机会;
const v = {
el: null,
html: `
<div>
<div class="output">
<span id="number">{{n}}</span>
</div>
<div id="actions">
<button id="add1">+1</button>
<button id="minus1">-1</button>
<button id="mul2">*2</button>
<button id="divide2">/2</button>
</div>
</div>
`,
init(container) {
v.el = $(container);
},
render(n) {
if (v.el.children.length !== 0) {
v.el.empty();
}
$(v.html.replace('{{n}}', n))
.appendTo(v.el);
}
}
C:controller,即控制器,负责其他所有代码,包括用户界面对用户输入的响应方式,并起到一定的组织和控制应用程序的作用。
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 #minus1': 'minus',
'click #mul2': 'mul',
'click #divide2': 'divide'
},
add() {
m.update({ n: m.data.n + 1 })
},
minus() {
m.update({ n: m.data.n - 1 })
},
mul() {
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
EventBus 也称事件总线,通过 EventBus 可以引入沟通桥梁的概念,可以向该总线发送事件和接收事件,从而达到沟通的目的。EventBus 的 API 主要有如下几个:
- 初始化:首先要创建一个 .js 文件,我们不妨让他叫做 EventBus.js。
//EventBus.js
import $ from 'jquery'
export const EventBus = new EventBus()
//在每个需要用到 EventBus 的文件中引入
import EventBus from './base/EventBus';
- 发送事件:
const eventBus = new EventBus()
const localKey = 'app2.index';
//所有数据相关都放到M
const m = new Model({
//初始化数据
data: {
index: parseInt(localStorage.getItem(localKey)) || 0
},
update(data) {
Object.assign(m.data, data); //把data所有的属性一个个赋值给m的data
eventBus.trigger('m:updated')
localStorage.setItem(localKey, m.data.index)
},
})
$on,$off,$trigger:
class EventBus {
constructor() {=
this._eventBus = $(window)
}
on(evenName, fn) {
return this._eventBus.on(evenName, fn);
}
trigger(evenName, data) {
return this._eventBus.trigger(evenName, data);
}
off(evenName, fn) {
return this._eventBus.off(evenName, fn);
}
}
表驱动编程
表驱动编程也是一种设计模式,主要是借助数据结构的知识,可以把一些类似的、重复的代码转换成哈希表来让代码变简单:
events: {
'click #add1': 'add',
'click #minus1': 'minus',
'click #mul2': 'mul',
'click #divide2': 'divide'
},
add() {
m.update({ n: m.data.n + 1 })
},
minus() {
m.update({ n: m.data.n - 1 })
},
mul() {
m.update({ n: m.data.n * 2 })
},
divide() {
m.update({ n: m.data.n / 2 })
},
模块化
我理解的模块化其实就是一种把重复累赘的代码抽象出来,分成不同的功能板块来进行代码重构的过程,但是每一个模块之间应当有一定的联系,来达到某一部分数据变更的时候,另一模块会及时响应的效果,所以我们在写代码的时候可以引入 EventBus 的概念来在不同的模块之间串联。如实际过程中可能就是由用户与页面交互的时候, model 中的数据发生改变,我们要让 view 根据数据的变化作出一定的响应来达到想要的效果。
本文的参考文章来自:efe.baidu.com/blog/mvc-de…