从MVC开始,浅谈我眼中的模块化

究竟什么是MVC

  1. 传统意义上的MVC

    太古初期的经典MVC是一种架构设计模式,它通过关注点分离鼓励改进应用程序组织。

    MVC包括三类对象:

    • Model:模型,用于数据的管理,一旦数据发生变化,Model会通知相关的视图。
    • View:视图,负责显示,描绘的是Model的当前状态,当模型的数据发生改变,视图也会相应地刷新。
    • Controller:控制器,用于控制程序的流程,它监听并处理View的事件,更新Model,同时也负责处理Model上的数据变化,更新View。

    在JavaScript中,我们可以简单示例为:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    
    //Model
    const model = {
        data:{ }, // 存放的数据
        //数据的一些处理方法:增删改查
        create() {}, 
        delete() {},
        update() {},
        get() {}
    }
    
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    
    //View
    const view = {
        //初始化空容器
        el:null,
        //要插入的html
        html:`...`,
        //初始化容器函数
        init( container ){ view.el = $(container)},
        //渲染页面
        render( ){ } //视图就是对数据的渲染 view = render(data)
    }
    
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    
    //Controller
    const controller = {
        //初始化函数
        init( ){ },
        //将事件抽离,制成Hash表
        events: { },
        //事件需要执行的函数,例如加减乘除
        add( ){ },
        minus( ){ },
        mul( ){ },
        divide( ){ }
        //或自动绑定事件
        autoBindEvents( ) { }
    }
    

如何理解模块化

  1. EventBus

    EventBus主要应用于对象间的通信。在后期JavaScript的MVC演化中逐渐发展出来的MVVM模式,Model与View是两个相互隔绝的存在,使用EventBus可以监听相应事件,使不同模块正常通信。

    Vue就是近似于MVVM模式的架构(但并没有完全遵循),它起到了View-Model层的作用。我们可以实例化并暴露一个Vue事件作为我们的EventBus(事件总线),来进行Model层与View层之间的通信。

    1
    2
    
    import Vue from 'vue'
    export const EventBus = new Vue( )
    

    如果非借助外力,诚恳地手写EventBus,它往往拥有on( ){ }监听事件,trigger( ){ }触发事件,off( ){ }解绑事件等必要API。

    ⚠️实际上目前一些模式的概念已经极近模糊,本着黑猫白猫只要能写出好的代码就是好猫的原则,归纳所谓的MV*模式是永远没有尽头的,关键在于如何以解绑分离(Model层与View层隔离)为切入点构建强壮且优雅的项目。

  2. 表驱动编程

    表驱动编程,我流顾名思义,以表格(哈希表)作为基本驱动来进行编程。基于非常浅显的理解,业务逻辑在笔者眼里就是if - elseswitch - case循环,复杂的逻辑就是无尽的if - elseswitch - case循环。

    这样写出来的代码不仅可读性不强,而且弯弯绕绕难以维护,实乃💩山预备选手。如果这时我们基于表驱动编程,将庞大的if值存入一个哈希(Hash)表,然后直观得从表内取值,岂不美哉?

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    
    //我在某款二游里,想确定这个角色的武器类型
    //无尽的if-else循环
    if('Yea Miko'){
        return 'Catalyst'
    }else if('Raiden Shogun'){
        return 'Polearm'
    }else if('Kamisato Ayaka'){
        return 'Sword'
    } else if...
    
    //转换思想,进行表驱动编程
    
    const list = {
        'Yea Miko' : 'Catalyst',
        'Raiden Shogun' : 'Polearm',
        'Kamisato Ayaka' : 'Sword'
        ...
    }
    for (let key in list){
        return value
    }
    
    //懂的人加我 uid 125586913🐶🐶 (⁎⁍̴̛ᴗ⁍̴̛⁎)
    

    表驱动编程的根本意义就在于将逻辑与数据分离。只抽离出重要的数据绘制成表,脱离逻辑的「枷锁」,基本上就不会出现难以维护的代码。后续如果需要增删改查,那么直接在表内进行操作也很难出错。

  3. 我如何理解模块化

    分离与切割,然后通过穿针引线🪡来重新支撑起整个项目,是我对模块化的直观理解。

    我认为能够将一个项目(无论大小)都进行模块化的封装,经脉分明的呈现是当今每一位码农都应该贯彻的思想。模块内部功能独立实现,只暴露相应的接口供给调用,与其他模块进行通信,除此以外完全分离。

    贯彻这种思想的代码一般来说都是结构清晰的,并且便于维护,对功能进行更替修改可以非常直观的落实到位,且模块内部数据独立私有,避免了大量冲突,大幅度解耦,同时也极大的提高了代码的利用效率。