浅析MVC

MVC是什么

MVC 是一种设计模式,他将应用分为三个部分:

M 是 Model,数据模型,负责数据相关的任务

V 是 View,视图,负责用户界面

C 是 Controller,控制器,负责监听用户事件,然后调用 M 和 V 更新数据和视图

伪代码实现 MVC

M

1
2
3
4
5
6
7
8
9
10
11
M = {
data: { 程序需要操作的数据或信息 },
create: { 增数据 },
delete: { 删数据 },
update(data) {
Object.assign(m.data, data) // 使用新数据替换旧数据
eventBus.trigger('m:upate') // eventBus 触发'm:update'信息, 通知 View 刷新
},
get:{ 获取数据 }
}

V

1
2
3
4
5
6
7
8
V = {
el: 需要刷新的元素,
html: `显示在页面上的内容`
init(){
v.el: 需要刷新的元素
},
render(){ 刷新页面 }
}

C

1
2
3
4
5
6
7
8
9
10
11
12
13
14
C = {
init(){
v.init() //初始化 V
v.render() // 第一次渲染页面
c.autoBindEvents() // 自动的事件绑定
eventBus.on('m:update',()=>{v.render()} // 当 enentsBus 触发 'm:update' 时 V 刷新
},
events:{事件以哈希表的方式记录存储},
method(){
data = 新数据
m.update(data)
},
autoBindEvents(){自动绑定事件}
}

mvc-demo

EventBus

EventBus 又称为事件总线,可以用来进行组件之间的监听和通信。

比如说当 Model 模块中的数据发生更新,触发了 EventBus 上的某个事件,而 Controller 恰好在监听这个事件,当这个事件触发时,Controller 就知道 Model 中的数据发生了更新了,从而做出一些反应

常用 API

  • EventBus.on() 监听事件
  • EventBus.trigger() 触发事件
  • EventBus.off() 解绑事件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class EventBus {
constructor() {
this._eventBus = $(window)
}

on(eventName, fn) {
return this._eventBus.on(eventName, fn)
}

trigger(eventName, data) {
return this._eventBus.trigger(eventName, data)
}

off(eventName, fn) {
return this._eventBus.off(eventName, fn)
}
}

表驱动编程

《代码大全》对表驱动编程的描述:

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

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

例如:if else

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
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 '???'
}
}

改为表驱动

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
function translate(term) {
let terms = {
'1': '一',
'2': '二',
'3': '三'
}
return terms[term];
}

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




1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 示例二
c = {
events:{
'click #add1':'add',
'click #minus1':'minus',
'click #mul2':'mul',
'click #divide2':'div'
},
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)
}
}
}

转自表驱动编程

模块化

JavaScript modules 模块 MDN

模块就是实现特定功能的一组方法,而模块化是将模块的代码创造自己的作用域,只向外部暴露公开的方法和变量,而这些方法之间高度解耦。

一个应用的不同的功能分离成几个模块,需要什么功能就加载相应的模块。