![d83378c565846c1e0900fb8d544bf47e.png](https://i-blog.csdnimg.cn/blog_migrate/237eb721708837efa3cc2b497326e61f.png)
在说MVC之前先讲一知识,在我们初级者程序员写出来的代码很渣渣,在代码圈人称意大利面条式代码,大家很难接受。所谓的面条式代码:一团糟、代码重复率高,为此就有人发明了MVC框架。它的用途就是通过数据处理、事件绑定、重新渲染等模块化方式来把这一团糟糕的代码进行逐步简化成万金油的代码。
MVC模型:是一种架构型的模式,本身不引入新功能,只是帮助我们将开发的结构组织的更加合理,使展示与模型分离、流程控制逻辑、业务逻辑调用与展示逻辑分离。
那什么是MVC?
- M是modal(数据模型)的简称,它是用于操作所有数据。
- Model(模型):数据模型,提供要展示的数据,因此包含数据和行为,可以认为是领域模型或JavaBean组件(包含数据和行为),不过现在一般都分离开来:Value Object(数据) 和 服务层(行为)。也就是模型提供了模型数据查询和模型数据的状态更新等功能,包括数据和业务。
- V是view(视图)的简称,它是用于负责所有UI界面。
- 负责进行模型的展示,一般就是我们见到的用户界面,客户想看到的东西。
- C是controller(控制器)的简称,它负责其他。
- 接收用户请求,委托给模型进行处理(状态改变),处理完毕后把返回的模型数据返回给视图,由视图负责展示。 也就是说控制器做了个调度员的工作。
三个对象在代码中的具体实现,
1、M对象操作所有的数据
数据相关都放到m,(采用伪代码,理解思路即可)
const m = {
data: {数据a},
create() {}, //增
delete() {}, //删
update(data) {
Object.assign(m.data,data)//用新数据替换旧数据
eventBus.trigger('m:update')//eventBus触发'm:update'信息,通知View刷新界面
}, //改
get() {数据a} //查
}
2、V对象负责所有的UI界面
视图相关都放到v,代码如下:
const v = {
el: 需要刷新的元素,
html: `
body里面的内容
`,
init(container) {
v.el = $(container)
}, //初始化容器
render(n) {
if (v.el.children.length !== 0) v.el.empty()
$(v.html.replace('{{n}}', n))
.appendTo(v.el) 刷新页面}
//通过if else判断容器的后代是否存在进行增删,最后渲染到页面
}
3、C控制器
C里面主要是放一些事件的操作,如:click、on等等;这里面又设计到EventBus、表驱动编程等 代码如下:
const c = { //初始化容器
init(container) {
v.init(container)//初始化View
v.render(m.data.n)//第一次渲染页面
c.autoBindEvents()//自动的事件绑定
eventBus.on('m:update',()=>{v.render(m.data.n)}//当enentsBus触发'm:update'是View刷新
},
事件太多,通过哈希表来一一列出,也正是我们所说的表驱动编程
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)
}
}
}
export default c
这个就是我们把index.html、css、js通过MVC进行改写,让代码由面条式变成了万金油(也就是模块化);
二、EventBus 有哪些 API,是做什么用的
1、什么是EventBus?
简单的说,就是一个以事件为驱动的消息服务总线
2、Web平台运行期为什么要用EventBus?
- 便于业务逻辑解耦
- 提供丰富的扩展点,包括前扩展、后扩展和覆盖
- 使用事件驱动,让事件触发更加清晰
- 让代码更加简洁清楚
3、Web平台运行期在那些地方使用了EventBus?
- 业务逻辑调度中心,包括前端、Web服务端任何地方
- 通过EventBus集成各种超类、模板、页面
- 通过EventBus集成各种系统服务与业务组件
4EventBus
基本的 API 有 on
(监听事件), trigger
(触发事件), off
(取消监听)方法。
用于模块间的通讯, view
组件层面,父子组件、兄弟组件通信都可以使 eventbus
处理
//EventBus.j代码
class EventBus{
constructor(){
this._eventBus =$(window)
}
on(eventName, fn){
return this._eventBus.on(eventName,fn)
}
trigger(eventName,data){
return this._trigger.tiggger(eventName,data)
}
off(eventName, fn){
return this._eventBus.off(eventName,fn)
}
}
export default EventBus
//new.js代码
import EventBus from 'EventBus.js'
const e =new EventBus()
e.on()
e.trigger()
e.off()
表驱动编程是做什么的?
表驱动法是一种编程模式,从表(哈希表)里面查找信息而不是使用逻辑语句(if…else…switch,可以减少重复代码,只将重要的信息放在表里,然后利用表来编程,与逻辑语句相比较有着更稳定的复杂度。
bindEvents(){
v.el.on('click','#add1',()=>{
m.data.n +=1
v.render(m.data.n)
})
v.el.on('click','#minus1',()=>{
m.data.n-=1
v.render(m.data.n)
})
v.el.on('click','#mul2',()=>{
m.data.n*=2
v.render(m.data.n)
})
v.el.on('click','#divide2',()=>{
m.data.n/=2
v.render(m.data.n)
})
}
上面这段代码相似性很高,我们使用表驱动将事件取出一个哈希表,使逻辑和数据清晰明了的分开后的代码:
events:{
'click #aa1':'add',
'click #minus1':'minus',
'click #mul2':'mul',
'click #divide2':'div'
},
add(){
m.update( data: {n:m.data.n +1})
},
minus(){
m.update( data:{n:m.data.n -1})
},
mul(){
m.update( data: {n:m.data.n *2})
},
div(){
m.update(data: {n:m.data.n /2})
}
会发现通过表驱动编程之后代码逻辑变的更为清晰简洁了。