MVC的介绍
MVC(Model-View-Controller)是一种万金油似的设计模式,所有的页面都可以使用MVC来优化代码结构。
每个模块都可以写成三个对象:分别是M、V、C
M-Model(数据类型)负责操作所有数据
示例代码如下:
// 数据相关都放到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-View(视图)负责所有ui界面
示例代码如下:
// 视图相关都放到v
const v = {
el: null,
html: `
<div>
<div class="output">
<span id="number">{{n}}</span>
</div>
<div class="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(控制器)负责其它
示例代码如下:
// 其他都c
const c = {
init(container) {
v.init(container)
v.render(m.data.n) // view = render(data)
c.autoBindEvents()
eventBus.on('m:updated', () => {
console.log('here')
v.render(m.data.n)
})
},
events: {
'click #add1': 'add',
'click #minus1': 'minus',
'click #mul2': 'mul',
'click #divide2': 'div',
},
add() {
m.update({n: m.data.n + 1})
},
minus() {
m.update({n: m.data.n - 1})
},
mul() {
m.update({n: m.data.n * 2})
},
div() {
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的介绍
我们想实现m.data数据更新的时候提示c.render来重新渲染的时候得用到事件监听和触发,所以我们来引用一个eventBus来实现对象间的通信。
部分代码如下:
const eventBus = $(window)//创建eventBus
eventBus.trigger('m:updated')//调用eventBus的trigger触发
eventBus.on('m:updated', () => { //调用eventBus的on注册事件
console.log('here')
v.render(m.data.n)
})常用的eventBus的Api有:trigger(触发事件)、on(注册事件)、off(取消事件)
表驱动编程
所谓表驱动法(Table-Driven Approach),简单讲是指用查表的方法获取值。
我们平时查字典以及念初中时查《数学用表》找立方根就是典型的表驱动法。在数值不多的时候我们可以用逻辑语句(if 或case)的方法来获取值,但随着数值的增多逻辑语句就会越来越长,此时表驱动法的优势就显现出来了。
比如我们想实现上面的监听事件:
$('#add').on('click', ()=>{
number += 1
$number.text(number)
localStorage.setItem('number', number)
})
$('#minus').on('click', ()=>{
number -= 1
$number.text(number)
localStorage.setItem('number', number)
})
$('#mult).on('click', ()=>{
number *= 2
$number.text(number)
localStorage.setItem('number', number)
})
$('#divide).on('click', ()=>{
number /= 2
$number.text(number)
localStorage.setItem('number', number)
})但是我们可以用一个哈希表来实现我们的需求,代码如下:
events: { //哈希表
'click #add1': 'add',
'click #minus1': 'minus',
'click #mul2': 'mul',
'click #divide2': 'div',
},
add() {
m.update({n: m.data.n + 1})
},
minus() {
m.update({n: m.data.n - 1})
},
mul() {
m.update({n: m.data.n * 2})
},
div() {
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)
}
}表驱动编程的优点
- 提高了程序的可读性。
- 减少了重复代码。
- 降低了复杂度。
- 程序有一个明显的主干。
我对模块化的理解
我觉得模块化就是将一个复杂的程序依据一定的规则(规范)封装成几个块(文件), 并进行组合在一起 ,块的内部数据与实现是私有的, 只是向外部暴露一些接口(方法)与外部其它模块通信。
比如我们在做一个页面的时候,需要有多个功能,比如可以简单的计算,可以进行TAB切换,可以进行点击移动、可以悬浮变色...这个时候我们可以把几个功能模块化,分成几个模块,我们可以用export导出模块,import引入模块,来实现我们想要的功能,而且代码不会显得那么冗余。
模块化编程的好处有:
多人协作互不干扰 模块化避免了变量污染,并且可以使得分工更加容易
灵活架构,焦点分离 可以将独立的功能从主干中分离开来单独开发,增加效率
方便模块间组合、分解 、解耦 降低各个功能模块间的耦合度
方便维护和管理
方便单个模块功能调试、升级
前端小白,如有错误请留言指正!!!