了解MVVM模型的雏形MVC

200 阅读3分钟

前言

根据这篇文章我们对比了三大框架各自的特点,并且了解到了Vue是一个以视图为核心的框架,其中重要一点就是MVVM设计模型。 MVVM这个架构模型我们经常能听到, 它源于经典的设计模型MVC。 因为自己最近在重新学习Vue,也要彻底搞懂MVVM这个模式的基本逻辑由此先从它的前身MVC来入手分析它的工作原理以及为什么要对MVC进行改进升级为MVVM。

1. MVC起源

前端MVC起源于后端,为几个单词的缩写

  • M: model 数据模型层, 主要是操作数据库(增删改查);
  • V: view 视图层;
  • C: controller 控制层 逻辑层, 数据和视图关联挂载和基本的逻辑操作;

操作流程

  1. 前端请求url;
  2. c层控制器方法启动调用model层;
  3. model层通过方法去操作数据库读取数据返回给c层控制器;
  4. c层控制器又将数据返回给前端;

2. 前端MVC各个概念和基础案例

各层的作用: Model: 管理视图所需要的数据, 将数据与视图关联起来; View: html模板和视图渲染; Controller: 注册和管理事件逻辑;

流程图示:

image.png

3. 简单的MVC案例

图示: 当我们修改xy的值会自动进行运算并且渲染。

指令12.gif

我们根据MVC用三个对象model view controller来模拟

(function () {
    let model = {
        data: { x: 0, y: 0,  res: 0 },
        init() {
            for(let key in this.data) {
                if (this.data.hasOwnProperty(key)) {
                    Object.defineProperty(this, key, {
                        get() {
                            return this.data[key];
                        },
                        set(newVal) {
                            // 2.每次设置驱动view层进行渲染页面
                            this.data[key] = newVal;
                            view.render({[key] : newVal});
                        }
                    })
                }
            }
        }
    };
    let view = {
        template: `
            <span class="val-x">{{ x }}</span>
            <span>+</span>
            <span class="val-y">{{ y }}</span>
            <span>=</span>
            <span class="val-res">{{ res }}</span>
            <div>
                <input class="inp x"  placeholder="x:value">
                <input class="inp y"  placeholder="y:value">
            </div>
        `,
        render(modifyVal) {
            // 第一次渲染情况
            if (!modifyVal) {
                let dom = document.createElement('div');
                // 替换模板
                this.template = this.template.replace(/\{\{(.*?)\}\}/g, (node, key) => {
                    return model[key.trim()]
                })
                dom.innerHTML = this.template;
                document.getElementById('app').append(dom);
            } else {
                for (let key in modifyVal) {
                    // 修改模板的时候只修改显示, 结果数据通过c层的input改变事件进行操作
                   document.querySelector('.val-' + key).textContent = modifyVal[key]
                }
            }
        }
    };
    let controller = {
        init() {
            let inputs = document.querySelectorAll('.inp');
            for (let i = 0; i < inputs.length; i++) {
                inputs[i].addEventListener('input', this.handleInput, false)
            }
        },
        handleInput(e) {
            let tar = e.target,
                field = tar.className.split(' ')[1];
            // 修改模型层数据驱动视图层改变
            model[field] = Number(tar.value);

            // 修改计算结果
            with(model) {
                res = eval('x + y');
            }
        }

    };

    init();
    function init() {
        // 1.数据层进行数据劫持, 优先处理数据
        model.init();
        // 初始化视图层
        view.render();
        // 初始化控制层绑定数据
        controller.init();
    }
})();

4. MVC缺陷

通过案例我们可以看到MVC设计模式中最大的缺陷在于驱动不明显, 各个驱动放到了各个层里。 数据劫持的驱动放在了model层中, 渲染模板的render函数放在了view层, 事件处理函数放在了controller层。驱动层并没有放在一个集合. 如果用户只考虑模板、数据以及逻辑那就更为轻松(vue使用的是这种思想)。

所以我们需要把模板的数据管理、渲染管理、事件处理的绑定管理集合起来形成了ViewModel层,剩下的Model层管理数据, View层管理视图这两个关联就靠ViewModel这就是MVVM,第二篇文章会详细说明MVVM的基本过程。

5. 总结

这是Vue专栏的第一篇文章,在掘金中也看过很多关于Vue的文章,感觉没有一个专栏对Vue进行深度解析, 所以我就开了这么一个专栏, 一个是为了自己更加深入的理解Vue的工作流程,二个也是希望能和大家一起探讨(哈哈虽然没人看),但还是希望自己能加持下去, 先立下一个flag!每3天至少更新一篇 ヾ(◍°∇°◍)ノ゙加油