一、MVC 是什么?
MVC 是一种软件设计模式。
对 MVC 软件设计模式可以分为三部分:
- Model:模型所持有所有的数据、状态和程序逻辑。
- View:负责页面的布局和显示。
- Controller:负责模型和界面之间的交互。
二、实现下面例子来展示 MVC 设计模式
点击相应的按钮,实现对数字的加减乘除操作。
各部分的伪代码实现(以下代码全为 js 代码)
1.引入文件
import './app1.css'
import $ form 'jquery' // 先全局安装 jQuery 再引入
2.声明 eventBus
const eventBus = $(window)
// eventBus 会提供 on()、off() 和 trigger() 方法
3.Model
// 与数据相关的都放到 m 对象中
m ={
date:{ 数据 },
create:{ 增加数据 },
delete:{ 删除数据 },
update(date) { // 更新数据
Object.assing(m.date,date) // 新的数据替换为旧的数据
eventBus.trigger('m:upate') // 触发 'Model:upate' 事件
localStorage.setItem('n', m.data.n) // 将数据保存下来
}
get:{ 查看数据 }
}
4.View
// 与视图相关的都放到 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) { // 重新渲染 html
if (.el.children.length !== 0) v.el.empty()
$(v.html.replace('{{n}}', n))
.appendTo(v.el)
}
}
5.Controller
// 其他都放到 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 #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)
}
}
}
6.表驱动编程+autoBindEvents
当你看到大批类似但不重复的代码,找到重要的数据,把重要的数据做成哈希表,就能简化代码了,且更加直观。 表驱动编程的意义在于数据与逻辑分离。
bindEvent(){
v.el.on('click','#add1',()={
m.date.n += 1
v.remder(m.date.n)
})
v.el.on('click','#minus1',()={
m.date.n -= 1
v.remder(m.date.n)
})
v.el.on('click','#mul2',()={
m.date.n *= 1
v.remder(m.date.n)
})
v.el.on('click','#divide2',()={
m.date.n /= 1
v.remder(m.date.n)
})
}
上面绑定事件的代码很类似但是又不重复,我们就简化成下面的样子,虽然下面的代码要比上面的代码多几行,但是很清晰。如果上面的绑定事件有 100 个或者是更多,下面的代码明显更加简单。或者当需要添加或者修改绑定的时间时,只需要更改哈希表中的数据就行,更加方便。
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)
}
}
7.EventBus
用 jQuery 声明一个 eventBus ,const eventBus = $(window),
eventBus 会提供 on()、off() 和 trigger() 方法
在上面的例子中,
eventBus.trigger('m:upate') // 触发 'm:upate' 事件
和
eventBus.on('m:updated', () => { // 监听 'm:upate' 事件
v.render(m.data.n)
})
一个 on() 方法和一个 trigger() 方法 ,当 on() 方法监听到 n 改变时,trigger() 方法就可以执行对应的事件,对页面中的 n 进行渲染,就可以实现对象之间的通信。
8.模块化
模块化是指解决一个复杂问题时自顶向下逐层把系统划分成若干模块的过程,有多种属性,分别反映其内部特性。
上述图片为四个不同功能的app,为app1,app2,app3,app4,将其css文件和js文件分开来写。这就是模块化。
MVC 也是模块化的一种,将一个项目分为 M ,V ,C 三个模块分别写里面的内容,但是各个模块之间是相互联系的。