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

 

 

 

 

 

 

posted @ 2020-09-03 21:32  没有茅台喝啤酒也行  阅读(210)  评论(0编辑  收藏  举报