一、MVC
-
M:Model,数据模型,负责操作所有数据,对数据进行增删改查
-
V:View,视图层,负责所有UI界面
-
C:Controller,控制器,负责操作视图层传输的指令,选取数据模型中的的数据,并对其操作
这三层是紧密联系在一起的,但又是互相独立的,每一层内部的变化不影响其他层。每一层都对外提供接口(Interface),供上面一层调用
eg:以一个页面中的数据进行简单计算为例子进行说明
1.1数据模型
//示例:
const m = {
data: { n: parseInt(localStorage.getItem('n')) || 100}, //数据源,100为保底值
create(){},//增加数据
delete(){},//删除数据
update(data){ //更新数据
Object.assign(m.data,data)
eventBus.trigger('m:updated')//eventBus触发事件,视图层刷新界面
localStorage.setItem() //用于数据缓存
},
get(){}//获取数据
}
1.2视图层
//示例:
const v = {
el:null,//要刷新的元素
html: ``, //元素的内容
init(container) { //插入到哪个容器里面
v.el = $(container)
},
render(n) { //渲染HTML
if(v.el.children.length !== 0) v.el.empty()
$(v.html.replace('{{n}}',n))
.appendTo(v.el)
}
}
1.3控制器
//示例:
const c = {
init(container){
v.init(container) //container容器里面进行第一次渲染
v.render(m.data.n) //view = render(data) ,视图渲染数据
c.autoBindEvents() //自动绑定事件
eventBus.on('m:updated',()=>{ //当enentsBus触发'm:update'时View刷新
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){// 遍历events,然后自动绑定事件
const value = c[c.events[key]]
const spaceIndex = key.indexOf(' ')
const part1 = key.slice(0,spaceIndex) //得到'click'
const part2 = key.slice(spaceIndex + 1)//得到'#add1'
v.el.on(part1,part2,value)
}
}
}
export default c;
二、eventBus
2.2eventBus的作用
eventBus 主要用于组件之间的通信,它能够简化各组件间的通信,让我们的代码书写变得简单,能有效的分离事件发送方和接收方(也就是解耦的意思)
2.1eventBus提供的API
eventBus.on()监听事件
eventBus.trigger()触发事件
eventBus.off()取消监听事件
三、表驱动编程
表驱动编程是一种使你可以在表中查找信息,而不必用逻辑语句(if 或 case)来把他们找出来的方法。
表驱动编程的意义在于逻辑与数据的分离,使重复冗余的代码变的稳定简洁。
假设day的起始值为1,下面的代码就是为了输出某天是星期几
function weekday(day) {
if(day&7===0){
return '星期天';
}
else if(day%7===2){
return '星期二';
}
else if(day%7===3){
return '星期三';
}
else if(day%7===4){
return '星期四';
}
else if(day%7===5){
return '星期五';
}
else if(day%7===6){
return '星期六';
}
}
通过表驱动编程的思想,简化代码如下:
function week(days){
let weekdays=['星期天','星期一','星期二','星期三','星期四','星期五','星期六'];
return weekdays[days%7];
}
四、模块化
- 将一个复杂的程序依据一定的规则(规范)封装成几个块(文件), 并进行组合在一起
- 块的内部数据与实现是私有的, 只是向外部暴露一些接口(方法)与外部其它模块通信
例如1.3所举的例子,数据模型封装好了controller,可以导出接口
export default c; // 默认导出
如果在其他文件,如main.js中引入
import x from './app1.js'
五、总结
- 最小知识原则
- 在设计程序时,应当尽量减少对象之间的交互。 如果两个对象之间不必彼此直接通信,那么这两个对象就不要发生直接的相互联系。常见的做法是引入一个第三者对象,来承担这些对象之间的通信作用
- 事不过三原则
- 同样的代码写三遍,就应该抽成一个函数
- 同样的属性写三遍,就应该做成共用属性(原型或类)
- 同样的原型写三遍,就应该用继承