MVC架构模式
MVC 架构设计
MVC的思想很简单,就是“分层”。
以前写代码,都是所有的代码放在一起。功能实现了,但是显得很臃肿,不方便维护。
MVC的分层:分成三层。
M:Model 模型层 负责存储和提供数据
V:View 视图层 负责渲染页面
C:Controller 控制器层 负责实现逻辑交互
MVC的功能:
C是核心,可以从M中获取数据、更新数据 可以更新视图
V可以从M中获取数据 M只负责存储和提供数据

实现MVC:
define('MVC', [], function() {
// 定义MVC,来包装这个模块
let MVC = (function() {
// MVC分成三个部分:M, C, V
let M = (function() {
// 闭包中,存储模型数据
let _model = {};
// 返回值就是暴露的接口
return {
// 写数据
set(key, value) {
// 对属性名做处理
let arr = key.split('.'); // ['b', 'c', 'd', 'e']
// 取出最后一个属性
let saveKey = arr.pop(); // arr = ['b', 'c', 'd']
// 定义result存储每次判断的结果
let result = _model;
// 逐一遍历,存储数据
arr.forEach(item => {
// 判断item属性是否存在
if (result[item] === undefined) {
// 属性不存在,设置默认值
result[item] = {};
}
// 只有对象以及函数可以添加属性
if (result[item] !== null && (typeof result[item] === 'object' || typeof result[item] === 'function')) {
// 让result存储当前的结果
result = result[item]
} else {
// result[item]是值类型的,不能添加属性
throw new Error('属性' + item + '的数据类型是' + typeof result[item] + ',该类型不能添加属性')
}
})
// 存储数据
result[saveKey] = value;
// console.log(_model);
},
// 读数据
get(key) {
// 对属性名切割
let arr = key.split('.'); // ['b', 'c', 'd', 'e']
// 定义结果
let result = _model;
// 从左到右遍历每一个属性
arr.some(item => {
// 如果是undefined就没有必要再去遍历了
// 数组遍历可以中断的方法:some, every, find, findIndex
result = result[item];
// result是否为undefined
return result === undefined;
})
// 返回数据
return result;
}
}
})();
// 存储数据
// M.set('a', [1, 2, 3])
// // M.set('b.c', 100)
// M.set('b.c.d.e', [1, 2, 3])
// console.log(M.get('b.c.d.e'));
// console.log(M.get('b.c'));
// V
let V = (function() {
// 定义存储视图的容器
let _view = {}
// 返回值就是暴露的接口
return {
// 添加视图
add(name, fn) {
// 直接存储
_view[name] = fn;
},
// 渲染试图
render(name) {
// 找到该方法,将其执行, 可以将模型传递进来
return _view[name] && _view[name](M)
}
}
})()
// C
let C = (function() {
// 控制器
let _ctrl = {};
// 返回值就是暴露的接口
return {
// 存储控制器
add(name, fn) {
// 直接存储
_ctrl[name] = fn;
},
// 初始化控制器
init(name) {
// 将对应的控制器执行
_ctrl[name] && _ctrl[name](V, M)
},
// 执行所有的控制器
initAll() {
// 遍历控制器
for (let name in _ctrl) {
// 执行
this.init(name)
}
}
}
})()
// 定义观察者模式
let Observer = (function() {
// 消息系统
let _msg = {};
// 暴露接口
return {
// 订阅消息
on(type, fn) {
// 判断消息是否存在
if (_msg[type]) {
// 直接存储
_msg[type].push(fn);
} else {
// 新建消息管道
_msg[type] = [fn];
}
},
// 发布消息
trigger(type, ...args) {
// 如果存在消息,遍历消息管道,执行回调函数
_msg[type] && _msg[type].forEach(fn => fn(...args))
},
// 注销消息
off(type, fn) {
// 有消息回调函数,删除
if (fn) {
// 如果消息管道存在,并且有该回调函数, 将其删除
// >= <= > < === == << >> >>>
_msg[type] && _msg[type].indexOf(fn) >= 0 && _msg[type].splice(_msg[type].indexOf(fn), 1)
} else if (type) {
// 清空该消息管道
_msg[type] = [];
}
}
}
})()
// 暴露接口
return {
// 添加模型
addModel(key, value) {
// 存储模型
M.set(key, value)
},
// 添加视图
addView(name, fn) {
// 存储视图
V.add(name, fn);
},
// 添加控制器
addCtrl(name, fn) {
// 存储控制器
C.add(name, fn)
},
// 启动应用程序
install() {
// 逐一执行所有的控制器
C.initAll();
},
// 暴露整体
Observer,
// 将接口复制过来。
...Observer
}
})();
// 暴露接口
return MVC;
})

浙公网安备 33010602011771号