浅析MVC

123 阅读3分钟

一、MVC 三个对象

  • M : 模型(Model),用来数据保存。
  • V : 视图 (View) , 用户界面。
  • C : 控制器(Controller),业务逻辑。

各个部分的伪代码实现

Model

Model ={
     data:{程序需要操作的数据或信息},
     create:{增数据},
     delete:{删数据},
     update(data) {
        Object.assign(m.data,data) //使用新数据替换旧数据
        eventBus.trigger('m:updata') // eventBus触发'm:updata'信息,通知View刷新
     },
     get:{获取数据}
}

View

View = {
    el:需要刷新的元素
    html: `<h1>M V C</h1>...显示在页面上的内容`
    init(){
        v.el:需要刷新的元素
    },
    render(){刷新页面}
}

Controller

Controller = {
   init(){
      v.init() // View初始化
      v.render() // 第一次渲染
      c.autoBindEvents() // 自动的事件绑定
      eventBus.on('m:updata',() => { v.render() }) // 当eventBus触发'm:updata'时View刷新
   },
   events:{事件以哈希表方式记录},
   method(){
      data = 改变后的数据
      m.updata(data)
   },
   autoBindEvents(){ 自动绑定事件 }
}EventBus

二、eventBus

  • $on事件的订阅
$on(eventName,callback)
//参数1:事件名称  参数2:事件函数
//判断当前事件名称是否存在,如果不存在则创建一个key值为事件名称
//value为一个数组 将callback push到数组中

const eventList = {};
const $on = (eventName,callback)=>
     if(!eventList[eventName]){
         eventList[eventName] = [];
     }
     eventList[eventName].push(callback)
}
  • $off事件解绑
$off(eventName,[callback])
//参数1:事件名称  参数2:[事件函数]
//判断当前事件名称是否存在,如果存在继续判断第二个参数是否存在,如果存在则找到相对应的下标,然后将函数在数组中移除
//如果不存在则将整个数组清空

const eventList = {};
const $off = (eventName,callback)=>{
    if(eventList[eventName]{
          if(callback){
                 let index = eventList[eventName.indexOf(callback);
                 eventList[eventName].splice(index,1)
          }
    }else{
           eventList[eventName].length = 0
    }
}

export default = {
     $on,
     $emit,
     $off,
}
  • $emit事件的触发
$emit(eventName,[params])
//参数1:事件名称  参数2:[需要传递的参数]
//判断当前事件的名称是否存在,如果存在则遍历数组,得到所有的函数,
//并执行,然后将params当做实参传递到函数中去
const eventList = {};
const $emit = (eventName,params)=>{
    if(eventList[eventName]{
         let arr = eventList[eventName];
         arr.map((cb)=>{
             cb(params)
         })
     }
}

三、表驱动编程

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

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

// 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(){}
}

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

四、模块化理解

现代的前端应用程序功能越来越强大,代码量也越来越庞大。因此,将网页应用分为各个独立的模块单独开发,每个模块之间互不影响,可以使程序的结构更加清晰,方便维护。 现代浏览器已经原生支持了模块功能,使用export和import语句就可以实现。 在以前,实现一个应用需要引入html、css、js。有了模块化的思想,只需引入一个js就可以实现。 在main.js中引入各个模块的js,各个js再各自引用自己的css、创建自己的html。 我们还可以把这些模块用到的类,也封装成单独的模块,然后再将其引入到各个模块中。 如此,所有的模块都是独立的,互不影响,代码的层次结构会变得异常清晰。