一、MVC是什么
M:模型(Model):数据的获取与保存
V:视图(View):用户界面的展示与渲染。
C:控制器(Controller):负责根据用户从“视图层”输入指令,选取“数据层中的数据”,对其进行相应的操作(绑定事件等)
一个软件的实现可以分成3个部分,他们相互之间可以通信,根据他们的通信方式可以衍生出其他的几种设计模式
传统意义上的MVC各个部分之间的通信是单向的
- View 传送指令到 Controller
- Controller 完成业务逻辑后,要求 Model 改变状态
- Model 将新的数据发送到 View,用户得到反馈
各个部分的伪代码实现
Model
Model = {
data: { 程序需要操作的数据或信息 },
create: { 增数据 },
delete: { 删数据 },
update(data) {
Object.assign(m.data, data) //使用新数据替换旧数据
eventBus.trigger('m:upate') // eventBus触发'm:update'信息, 通知View刷新
},
get:{ 获取数据 }
}
复制代码
View
View = {
el: 需要刷新的元素,
html: `<h1>M V C</h1>....显示在页面上的内容`
init(){
v.el: 需要刷新的元素
},
render(){ 刷新页面 }
}
复制代码
Controller
Controller = {
init(){
v.init() // View初始化
v.render() // 第一次渲染
c.autoBindEvents() // 自动的事件绑定
eventBus.on('m:update', () => { v.render() }) // 当eventBus触发'm:update'时View刷新
},
events:{ 事件以哈希表方式记录 },
method() {
data = 改变后的新数据
m.update(data)
},
autoBindEvents() { 自动绑定事件 }
}EventBus
复制代码
MVP
MVP 模式将 Controller 改名为 Presenter,同时改变了通信方向。
其中model和view之间不再通信,而是通过presenter这个中介来实现交互,此时代码大部分分布在presenter上
MVVM
MVVM 模式将 Presenter 改名为 ViewModel,基本上与 MVP 没有区别。
唯一的区别是,它采用双向绑定(data-binding):View的变动,自动反映在 ViewModel,反之亦然。Angular 和 Ember 都采用这种模式。
二、eventBus
DOM 的事件机制就是发布订阅模式最常见的实现,这大概是前端最常用的编程模型了,监听某事件,当该事件发生时,监听该事件的监听函数被调用。eventBus就是实现发布订阅模式的一种方法。
这里可以看下发布订阅和观察者模式的小区别
其实jquery和vue构造出来的对象都有监听事件的方法,我们只需要构造一个对象,然后调用他的on 和 trigger方法就可以实现组件之间的通信
下面介绍几个vue常用的事件api及其内部实现
1.$on 事件的订阅
$on(eventName,callback)
//参数1:事件名称 参数2:事件函数
//判断当前事件名称是否存在,如果不存在则创建一个key值为事件名称
//value为一个数组 将callback push到数组中
const eventList = {};
const $on = (eventName,callback)=>{
if(!eventList[eventName]){
eventList[eventName] = [];
}
eventList[eventName].push(callback)
}
复制代码
2.$off 事件的解绑
$off(eventName,[callback])
//参数1:事件名称 参数2:[事件函数]
//判断当前事件名称是否存在,如果存在继续判断第二个参数是否存在,如果存在则找到相//对应的下标 然后将函数在数组中移除
//如果不存在则将整个数组清空
const eventList = {};
const $off = (eventName,callback)=>{
if(eventList[eventName]){
if(callback){
let index = eventList[eventName].indexOf(callback);
eventList[eventName].splice(index,1)
}
}else{
eventList[eventName].length = 0;
}
}
export default = {
$on,
$emit,
$off
}
复制代码
3.$emit 事件的触发
$emit(eventName,[params])
//参数1:事件名称 参数2:[需要传递的参数]
//判断当前事件的名称是否存在,如果存在则遍历数组,得到所有的函数,
//并执行。然后将params当做实参传递到函数中去
const eventList = {};
const $emit = (eventName,params)=>{
if(eventList[eventName]){
let arr = eventList[eventName];
arr.map((cb)=>{
cb(params)
})
}
}
复制代码
三、表驱动编程
我们先看一个简单例子来感受下表驱动,由于看了很多博客都是非要整的很复杂的代码,这样让人的关注点都在理解代码本身上了,所以我自己写了个很简单的例子
function age(name){
if(name==="小明"){
console.log("年龄是"+10)
}else if(name==="小白"){
console.log("年龄是"+14)
}else if(){
}
//....等等
}
复制代码
假如我们要写一个查询年龄的函数,如果用if else语句写,那么有多少人我们就得写多少个if else语句,这样我们的代码量是线性增长的,如果我们用一个哈希表来记录这些映射关系会怎样
const list={
"小明":10,
"小白":14,
//等等...
}
function age2(name){
if(name in list){
console.log(name+"的年龄是"+list[name])
}else{
console.log("查无此人")
}
}
复制代码