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; })