模块化与MVC

300 阅读5分钟

模块化编程

将一个复杂的程序依据一定的规则(规范)封装成几个块(文件)并进行组合。模块的内部数据的实现是私有的,只是向外部暴露一些接口(方法)与外部其他模块通信。这就是模块化。 好处:

  • 降低代码耦合度
  • 减少重复代码
  • 提高代码重用性
  • 在项目结构上更加清晰,便于维护。

在一个完整的页面应用中,不同的节点功能,不同的结构可以规划为多个模块,每个模块的实现的方式以及用到的技术大不相同,使用模块化编程可以减小各个模块之间的影响和联系,可以更方便的优化代码和重构代码,提高我们代码的重用性,便于后期维护;

简单来说,模块化就是把相对独立的代码从一大段代码里抽取成一个个小模块,每个模块之间相对独立,实现相应的功能,更加简洁美观,也方便维护。

什么是MVC

MVC 是什么

MVC 是一种软件架构模式,把软件系统分为三个基本部分:模型( Model )、视图( View )和控制器( Controller )

MVC的特点

优点:

  1. 耦合性低

    M、V、C三个模块相互之间的影响非常地小,当对其中一个模块进行维护升级、数据搬运等工作时,对其他的模块影响极小。

  2. 重用性高

    MVC允许使用各种不同样式的视图来访问同一个服务器端的代码。只需要改变View的实现方式即可,而无需对数据层,逻辑层进行改动。

  3. 部署快、可维护性高

    使用MVC模式使开发时间得到相当大的缩减。因为模块的分离,所以开发者可以主力攻坚其中一个模块,而不需要多头兼顾。而且由于分离了视图层和逻辑层,也更易于维护。

缺点:

  1. 定义模糊

    MVC的概念非常模糊,每个开发者可能对它的理解都不尽相同。

  2. 不适合中小型规模项目

    由于MVC整体比较复杂,对于中小型项目可能反而会使他们更加笨重。对于简单的界面,严格遵循MVC,使模型、视图与控制器分离,会增加结构的复杂性,并可能产生过多的更新操作,降低运行效率。

M-Model(数据模型)

负责操作所有数据,一旦模型的数据发生改变,Model将通知有关的视图。

//示例如下
const m = {
   data:{ 程序所需要的数据 },
   create(){ 增加数据 },
   delete(){ 删除数据 },
   get(){ 获得数据 },
   update(){ 修改数据 }
}

V-View(视图)

负责所有UI界面,描绘的是Model的当前状态,当模型的数据发生改变,View就会刷新自己。

//示例如下
const View={
    el:要刷新的元素,
    html:'要显示在页面上的刷新内容'
    init(){
        v.el:初始化需要刷新的元素
    },
    render(){
        刷新页面
    }
}

C-Controller(控制器)

负责根据用户从“视图层”输入指令,选取“数据层中的数据”,对其进行相应的操作(绑定事件等),产生最终结果.即负责监听并处理视图(View)的事件,更新和调用Model。也负责监听Model的变化,并更新View。

//示例如下
const Controller={
    init(){
        v.init()
        v.render()//第一次渲染页面
        c.autoBindEvents()//自动事件绑定
        eventBus.on('m:update',()=>{v.render()}//当enentsBus触发'm:update'时View刷新
    },
    events:{事件以哈希表的方式记录存储},
    method(){
        data=新数据
        m.update(data)
    },
    autoBindEvents(){自动绑定事件}
}

EventBus 的作用

上文中提到的 MVC 三层是紧密联系在一起,但又互相独立,每一层内部的变化不影响其他层。当层与层之间需要通信时,这时就需要用到 EventBus . 使用 EventBus 可以满足最小知识原则,model和view互相不知道对方的细节,但是却可用调用对方的功能。 EventBus 主要用于组件之间的监听与通信。

EventBus 的常用 API

  • on(监听事件)
  • trigger(emit)(触发事件)
  • off(取消监听)方法。
// on(监听事件)
const eventBus = $(window)
evnetBus.on("监听事件",() => {})

// trigger(自动触发事件)
const eventBus = $(window)
eventBus.trigger("事件")

// off(取消监听)
const eventBus = $(window)
eventBus.off("监听事件")

关于表驱动编程

表驱动方法是一种使你可以在表中查找信息,而不必用逻辑语句( if 或 case )来把他们找出来的方法。事实上,任何信息都可以通过表来挑选。在简单的情况下,逻辑语句往往更简单而且更直接。但随着逻辑链的复杂,表就变得越来越富于吸引力了。有大批类似但不重复的代码时,可以把这些重要的数据做成哈希表,通过遍历这个哈希表来进行批量的函数监听;这样就简化了代码。 表驱动编程的意义在于逻辑与数据的分离。

  • 以 if-else 为例
function translate(term) {
    if (term === '1') {
        return '一'
    } else if (term === '2') {
        return '二'
    } else if (term === '3') {
        return '三'
    } else {
        return '???'  
    }
}

// 如果想添加一个新的名词翻译,需要再添加一个if-else逻辑,例如:
function translate(term) {
    if (term === '1') {
        return '一'
    } else if (term === '2') {
        return '二'
    } else if (term === '3') {
        return '三'
    } else if (term === '4') {   
        // 此处添加了一个新的名词翻译
        return '四'
    } else {
        return '???'  
    }
}

  • 转化为表驱动
function translate(term) {
    let terms = {
        '1': '一',
        '2': '二',
        '3': '三'
    }
    return terms[term];
}

// 如果想添加一个新的名词翻译,只需要在terms中添加一个新的表项,不需要修改整个逻辑
function translate(term) {
    let terms = {
        '1': '一',
        '2': '二',
        '3': '三''4': '四'   // 添加一个新的名词翻译
    }
    return terms[term];
}
   let a = translate(2)
        console.log(a)