浅析MVC

189 阅读3分钟

今天我们来总结一下什么是MVC。

MVC是一种设计模式,当我们在编写JavaScript代码时,往往会因为封装不足或者需求过多而产生一篇又长又臭的代码,为了解决代码重复、页面重复的问题,我们可以使用MVC设计模式来进行代码重构。

MVC定义

MVC包括三大类对象,但是它们的定义并不是一成不变的,在不同的程序员眼中MVC所涵盖的内容不一定相同,这里只是列举我个人的看法和一些伪代码的例子:

M:model,即数据模型,我们可以将页面中所有操作数据的代码整合在M模块中以用来操作数据,一旦模型的数据发生变化,模型应当通知有关视图;

const m = {
    //初始化数据
    data: {
    n: parseInt(localStorage.getItem('n'))
    },
    create() { },
    delete() { },
    update(data) {
        Object.assign(m.data, data); //把data所有的属性一个个赋值给m的data
        eventBus.trigger('m:updated')
        localStorage.setItem('n', m.data.n)
    },
    get() { }
}

V:view,即视图,负责所有UI界面的代码应该整合在V模块中,描述了model模块当前的状态,当数据发生变化时,视图应该获得刷新的机会;

const v = {
    el: null,
    html: `
    <div>
        <div class="output">
            <span id="number">{{n}}</span>
        </div>
        <div id="actions">
            <button id="add1">+1</button>
            <button id="minus1">-1</button>
            <button id="mul2">*2</button>
            <button id="divide2">/2</button>
        </div>
    </div>
    `,
    init(container) {
        v.el = $(container);
    },
    render(n) {
        if (v.el.children.length !== 0) {
            v.el.empty();
        }
        $(v.html.replace('{{n}}', n))
            .appendTo(v.el);
    }
}

C:controller,即控制器,负责其他所有代码,包括用户界面对用户输入的响应方式,并起到一定的组织和控制应用程序的作用。

const c = {
    init(container) {
        v.init(container);
        v.render(m.data.n); //view = render(data)
        c.autoBindEvents();
        eventBus.on('m:updated', () => {
            v.render(m.data.n)
        })
    },
    events: {
        'click #add1': 'add',
        'click #minus1': 'minus',
        'click #mul2': 'mul',
        'click #divide2': 'divide'
    },
    add() {
        m.update({ n: m.data.n + 1 })
    },
    minus() {
        m.update({ n: m.data.n - 1 })
    },
    mul() {
        m.update({ n: m.data.n * 2 })
    },
    divide() {
        m.update({ n: m.data.n / 2 })
    },
    autoBindEvents() {
        for (let key in c.events) {
            const value = c[c.events[key]]
            const spaceIndex = key.indexOf(' ');
            const part1 = key.slice(0, spaceIndex);
            const part2 = key.slice(spaceIndex + 1);
            v.el.on(part1, part2, value);
        }
    }
}

EventBus

EventBus 也称事件总线,通过 EventBus 可以引入沟通桥梁的概念,可以向该总线发送事件和接收事件,从而达到沟通的目的。EventBus 的 API 主要有如下几个:

  1. 初始化:首先要创建一个 .js 文件,我们不妨让他叫做 EventBus.js。
//EventBus.js
import $ from 'jquery'
export const EventBus = new EventBus()

//在每个需要用到 EventBus 的文件中引入
import EventBus from './base/EventBus';

image.png

  1. 发送事件:
const eventBus = new EventBus()
const localKey = 'app2.index';

//所有数据相关都放到M
const m = new Model({

    //初始化数据
    data: {
        index: parseInt(localStorage.getItem(localKey)) || 0
    },

    update(data) {
        Object.assign(m.data, data); //把data所有的属性一个个赋值给m的data
        eventBus.trigger('m:updated')
        localStorage.setItem(localKey, m.data.index)
    },
})
  1. $on,$off, $trigger:
class EventBus {
    constructor() {=
        this._eventBus = $(window)
    }
    on(evenName, fn) {
        return this._eventBus.on(evenName, fn);
    }
    trigger(evenName, data) {
        return this._eventBus.trigger(evenName, data);
    }
    off(evenName, fn) {
        return this._eventBus.off(evenName, fn);
    }
}

表驱动编程

表驱动编程也是一种设计模式,主要是借助数据结构的知识,可以把一些类似的、重复的代码转换成哈希表来让代码变简单:

events: {
    'click #add1': 'add',
    'click #minus1': 'minus',
    'click #mul2': 'mul',
    'click #divide2': 'divide'
},
add() {
    m.update({ n: m.data.n + 1 })
},
minus() {
    m.update({ n: m.data.n - 1 })
},
mul() {
    m.update({ n: m.data.n * 2 })
},
divide() {
    m.update({ n: m.data.n / 2 })
},

模块化

我理解的模块化其实就是一种把重复累赘的代码抽象出来,分成不同的功能板块来进行代码重构的过程,但是每一个模块之间应当有一定的联系,来达到某一部分数据变更的时候,另一模块会及时响应的效果,所以我们在写代码的时候可以引入 EventBus 的概念来在不同的模块之间串联。如实际过程中可能就是由用户与页面交互的时候, model 中的数据发生改变,我们要让 view 根据数据的变化作出一定的响应来达到想要的效果。

本文的参考文章来自:efe.baidu.com/blog/mvc-de…

©本总结教程版权归作者所有,转载需注明出处