浅析MVC

151 阅读3分钟

一. MVC模式

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

这种模式用于应用程序的分层开发。

在 JavaScript 中,每个模块都可以写成三个对象,分别是 M、V、C。

  • M 是 Model(数据模型),负责数据相关的任务
  • V 是 View(视图),负责所有UI界面
  • C 是 Controller(控制器),负责监听用户事件,然后调用 M 和 V 更新数据和视图

MVC 三个对象的一些重要属性和方法如下:

import $ from 'jquery'
const eventBus = $(window)

//数据相关都放到 m
let m = {
    data: {},
    create() {},  //增
    delete() {},  //删
    update(data) {  //改
        Object.assign(m.data, data)
        eventBus.trigger('m:updated')  //触发 m:updated 事件,通知刷新
    }, 
    get() {}  //查
 }

//视图相关都放到 v
let v = {
    el: 要刷新的元素,
    html:`显示在页面上的内容`,
    init() {  //初始化
        v.el: ;
    },
    render() {}  //将数据渲染到页面
}

//其他都放到 c
let c = {
    init() {
        v.init()
        v.render()  //第一次渲染视图
        c.autoBindEvents()
        eventBus.on('m:updated', ()=>{  //监听 m:updated 事件,刷新页面
            v.render()
        })
    },
    events: {},  //使用哈希表记录的事件集合
    method() {
        m.update(data)
    },
    autoBindEvents() {}  //自动绑定事件
}

二. EventBus

EventBus 是一个用于组件间通信的框架。它为开发提供一种非常简便的方式来实现组件间解耦通信,并且提供了线程切换、优先级设置等功能,提高了开发的效率。

在MVC中使用 EventBus 可以满足最小知识原则,m 和 v 互相不知道对方的细节,但是却可以调用对方的功能

EventBus 常用的 API 有

  • .on(eventName, fn)监听事件
  • .trigger(eventName) 触发事件
  • .off(eventName, fn) 取消事件监听

一个简单的例子

add(){
    data += 1
    render(data)
}
minus(){
    data -= 1
    render(data)
}
multiply(){
    data *=2
    render(data)
}
divide(){
    data /= 2
    render(data)
}

以上代码是进行加减乘除的运算,想表达的意思就是:data 只要进行更新,就调用一次渲染函数。

使用EventBus改进代码

import $ from 'jquery'
const eventBus = $(window)  //使用jQuery创建一个eventBus

let m = {
    data: { n:100 },
}
update(data){
    Object.assign(m.data, data)  //批量赋值
    eventBus.trigger('m:updated')  //触发事件,事件名为 m:uodated
}
eventBus.on('m:updated', ()=>{  //监听事件 m:updated
    render(m.data.n)
})

/* 改进后的加减乘除函数 */
add(){
    update({n: m.data.n + 1})
}
minus(){
    update({n: m.data.n - 1})
}
multiply(){
    update({n: m.data.n * 2})
}
divide(){
    update({n: m.data.n / 2})
}

只要一调用update()函数,就会使eventBus.trigger('m:updated')触发,然后eventBus.on()就会监听到事件 m:updated,然后调用render()函数进行渲染。

三. 表驱动编程

表驱动法是一种编程模式,从表里面查找信息而不是使用逻辑语句(if...else...switch),在简单的情况下,用逻辑语句往往更简单而且更直接,但如果逻辑很复杂,表就变得越来越富有吸引力了。

在JS中,把重要的数据存在哈希表中,可以省掉大批类似但不重复的代码。

//事件集合的哈希表
events: {    
    "click #app1": "add",    
    "click #minus1": "minus",    
    "click #mul2": "mul",    
    "click #divide2": "div",
},
add() {    
    m.update({ n: m.data.n + 1 })
},
minus() {    
    m.update({ n: m.data.n - 1 })
},
mul() {    
    m.update({ n: m.data.n * 2 })
},
div() {    
    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)  
    }
}

四. 对模块化的理解

模块是实现特定功能的相互独立的一组方法。因为有了模块,我们能更好的管理网页的业务逻辑,以及按照自己的需求去使用各种模块,并且可以让每个开发者都能设计自己想要的模块以及去使用别人的模块方法。

模块化可以降低代码耦合度,减少重复代码,使代码可利用率更高,并且在项目结构上更加清晰,使得程序更容易维护。

对于JS模块:

可以使用export default x将一个变量默认导出给外部使用,

可以使用import x from './xxx.js' 引入另一个模块导出的默认变量,

可以使用import {x} from './xxx.js'引用另一个模块导出的名为 x 的变量。

相关文章