MVC简介和表驱动编程思想

819 阅读3分钟

一个复杂的、功能完善的应用程序往往拥有成千上万行的代码量,如果这些代码杂乱无章、冗余重复,势必会对开发和日后的维护升级造成很大的麻烦。因此,为了使代码层次分明、条理清晰,必须让它具备合理的架构,即架构设计模式。MVC就是最著名的设计模式之一,在前端领域也具有广泛的应用。

一、何为MVC

MVC模式将一个应用程序分为三个对象,M、V、C

  • M(Model):数据模型,负责数据及其相关的任务
const m = {
    data: {...},
    methods: {
        增、删、改、查...
    }
    ...
}
  • V(View):视图,负责用户界面
const v = {
    element: xxx,
    template: yyy,
    render(data){
        渲染用户视图
    }
    ...
}
  • C(Controller):控制器,用于控制应用程序的流程,处理用户事件,组织调度M和V更新数据和视图
const c = {
    bindEvents(){
        绑定用户事件    
    }
    ...
}

二、eventBus的作用

eventBus是一个对象,它可以用来完成上述M、V、C对象间的通信。

例如,我们希望当M中的数据变化时,能够自动触发V的render,使变化后的数据即时渲染到界面上,如何做到呢?

eventsBus提供了on、off、trigger等方法,用来处理事件。我们可以在M的data发生变动时,用trigger方法触发一个事件A(字符串):

m = {
    data: {...},
    methods: {
        ...
        update(data){
            修改m.data
            eventBus.trigger(A)
        }
    }
}

然后,用on方法监听这个事件A,一旦事件A触发(即数据变化了),就调用V的render重新渲染视图:

eventBus.on(A, ()=>{
    v.render(m.data)
})

如此,就实现了M和V之间的沟通,使得视图和数据保持同步。

三、表驱动编程

表驱动编程是一种很重要的编程思想,它的理念是从大量相似的代码中抽取出本质的东西,组成哈希表,利用表进行编程,以减少重复代码。

例如,需要给多个元素绑定不同的事件,直觉上我们会一个个地罗列:

// jQuery 风格写法
$('#el1').on('事件A', fn1)
$('#el2').on('事件B', fn2)
$('#el3').on('事件C', fn3)
$('#el4').on('事件D', fn4)
$('#el5').on('事件E', fn5)

一旦重复次数过多,代码就会变得冗余、臃肿。纵观整体,可以发现每行代码最关键的信息其实就是'#el'、'事件'和fn,将关键信息抽离,组成一个对象:

const events = {
    '#el1 事件A': 'fn1',
    '#el2 事件B': 'fn2',
    '#el3 事件C': 'fn3',
    '#el4 事件D': 'fn4',
    '#el5 事件E': 'fn5'
}

const eventFunctions = { //事件处理函数
    fn1(){}
    fn2(){}
    fn3(){}
    fn4(){}
    fn5(){}
}

然后创建一个函数,给这些元素绑定相应的事件:

function autoBindEvents(){
    for(let key in events){
        const spaceIndex = key.indexOf(' ')
        const element = key.slice(0, spaceIndex)  //得到各个'#el'
        const event = key.slice(spaceIndex + 1) //得到各个'事件'
        const fn = eventFunctions[events[key]] //得到各个fn
        $(element).on(event, fn) //绑定事件
    }
}

如此,就去除了所有重复的代码。乍看可能觉得更复杂了,但是当事件越来越多时,其简洁性就越来越显著。而且后续再添加新的事件时,只需在events对象中添加即可,非常便捷。

四、模块化思想

现代的前端应用程序功能越来越强大,代码量也越来越庞大。因此,将网页应用分为各个独立的模块单独开发,每个模块之间互不影响,可以使程序的结构更加清晰,方便维护。

现代浏览器已经原生支持了模块功能,使用exportimport语句就可以实现。

在以前,实现一个应用需要引入html、css、js。有了模块化的思想,只需引入一个js就可以实现。

在main.js中引入各个模块的js,各个js再各自引用自己的css、创建自己的html。

我们还可以把这些模块用到的类,也封装成单独的模块,然后再将其引入到各个模块中。

如此,所有的模块都是独立的,互不影响,代码的层次结构会变得异常清晰。