浅析MVC

668 阅读3分钟

1、历史

1.1、背景

  1. 原始网页需要摧毁DOM再创建
  2. SPA(Single Page Application),一个页面DOM加载完后不刷新,通过ajax部分刷新,率先使用它的是Gmail
  3. SPA的出现需要更新交互模式,MV*框架变得越来越重要

1.2、发展历程

  1. 直接操作DOM

    • jQuery(选择器、兼容性)兼容ie的版本臃肿
    • zepto.js(选择器)在移动端表现好
  2. MVC模式

    • 理想的MVC模型

      • M(数据)
      • V(更新DOM)
      • C(调用Module给V渲染)

image.png - 被玩坏了的MVC:

    -   禁止M和V通信不现实,js无法非常容易的禁用
    -   MVC中M和V通信,在安卓等设备也存在

image.png

  1. MVP模式

    • M:用于存放数据

    • V:影响用户交互

    • Presenter:

      • M改变,修改DOM
      • V相应交互时通知Presenter,Presenter负责更新Presenter,及修改DOM

image.png

  1. MVVM模式

    • M:存放数据
    • V:影响用户交互
    • ViewModule:可以理解为自动化调用Presenter

image.png

2、MVC三个模型分工

2.1、Model

  • 数据管理,主要负责和服务器进行交互,将请求到的数据传给Controller。
const m = {
    data: {},
    create() {增 },
    delete() { 删},
    update() {改},
    get() {查}
}

2.2、View

  • 负责用户界面,HTML 渲染
const v = {
    el: null,
    // 初始化html
    html: `代码`
    ,
    init(container) {
        v.el = $(container)
    },
    render(n) { }
}

2.3、Controller

  • 负责监听并处理View 的事件,更新和调用 Model,也负责监听 Model的变化并更新 到View
const c={
  init(container){}
  events:{事件}
  add(){执行}
  minus(){执行}
  update(){执行}
  get(){执行}
  autoBindEvents(){逻辑}
}

3、EventBus

3.1 EventBus的 API

on:监听事件
trigger:触发事件
off:取消监听

3.2 EventBus的作用

用于模块间的通讯

3.3 示例代码

import $ from "jquery";
class EventBus{
    constructor() {
        this._eventBus = $(window);
    }
    on(eventName,fn){
        return this._eventBus.on(eventName,fn)
    }
    trigger(eventName,data){
        return this._eventBus.trigger(eventName,data)
    }
    off(eventName,fn){
        return this._eventBus.off(eventName,fn)
    }
}
export default EventBus

4、表驱动编程

4.1、概述

  • 表驱动法是一种编程模式(scheme),从表里面查找信息而不使用逻辑语句(if或case)

4.2、作用

  • 对简单的情况而言,使用逻辑语句更为容易和直白,但随着逻辑链的越来越发杂,表驱动编程的方式更高效
const c = {
    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)
        }
    }
}

5、如何理解模块化

5.1 概述

  • 模块化就是为了减少系统耦合度,提高高内聚,减少资源循环依赖,增强系统框架设计
  • 开发者便于维护,同时也让逻辑相同的部分可复用

5.2对比

若M有3种,数据有2种,c可能为6种

  1. Copy-Ppaste-Modify的写法,代码复用性非常差,是一个差劲的方法

    • 代码写三遍,就应该抽象为函数 ;属性写三遍,就应该抽象为公用属性(原型或类);原型写三遍,就应该继承;常量就应该是const
  2. MVC的写法

    • 代码可复用,不需要复制粘贴

6、MVC框架缺陷

  1. 原生HTML+CSS+JavaScript分离:属于文件格式分离,本质不是“分而治之[1]”的,在JavaScript中业务逻辑和界面渲染逻辑混在一起,只方便了文件管理,所以势必无法用于构造大型前端应用

  2. Facebook开始使用MVC模式,但他们很快发现

    • MVC模式让代码变得复杂,主要表现为模块间依赖和耦合增加,改一处修改多处
    • 问题在于:MVC框架中,开发者为了省事,经常不扩展Controller,而是直接在Model和View之间通信

  1. 工程化:将大问题拆分为小问题,第一步做什么,第二部做什么 ↩︎