浅析MVC

123 阅读1分钟

MVC的三个对象

Model(数据模型)

Model用于封装与应用程序的业务逻辑相关的数据以及对数据的处理方法,会有一个或多个视图监听此模型。一旦模型的数据发生变化,模型将通知有关的视图。

  • 读取数据库数据
  • 写入html
//伪代码
Model = {
  $.get('/user/1').then(function(user){
    template = (
      <h1>{{ name }}</h1>  
    )
      // 暂时还不知道要填入的数据是什么,用一个占位符表示
    content = template.replace('{{ title }}', user.name)
      // 用从数据库获取到的数据替换占位符
    $app.html(content)
      // 放到页面里
	$form.on('submit', function(){
	  // 用户提交数据
      $.post('/user/1', $form.serialize()).then(function(){
	  // AJAX提交异步请求
          alert('提交成功')
    })
  })
}

View(视图)

视图view是它在屏幕上的表示,描绘的是model的当前状态。当模型的数据发生变化,视图相应地得到刷新自己的机会。

  • 处理content,使它与HTML结合
View = {
	// 集中处理用户事件
    // 渲染HTML模板
    // 与Model交互
 	el: '需要刷新的元素' // 通常使用EventBus作为共有属性继承,来获取页面元素
    html: '需要插入元素内的HTML内容'
    render: { 渲染html }
    }

Controller(控制器)

控制器controller定义用户界面对用户输入的响应方式,起到不同层面间的组织作用,用于控制应用程序的流程,它处理用户的行为和数据model上的改变。

  • 监听Model,变化时更新View
  • 监听用户交互事件,更新Model
Controller = {
  function showUser (userId)
    user = UserModel.find(userId) // 从Model获取 user 数据
    content = readFile('user.html') // 获取 user.html 内容
    response = render(content, user) // 将 user 数据填入 HTML 中
    return response // 返回给用户
}

EventBus的作用

  • 模块通信:在模块化处理时,各模块互不知道其他模块的存在,不能直接相互获取数据,EventBus的存在就解决了模块之间通信的问题。
  • 使用:在EventBus模块里监听它的事件,在想使用的地方引入EventBus来触发。
// 伪代码
EventBus {
	constructor{ this._eventbus = $(window) }
     // 从引用的库里(如jQuery、Vue)获取到,后期改动引用库比较方便
	on(eventName, fn) {
    return this._eventBus.on(eventName, fn)
	}
	trigger(eventName, data) {
	}
	off(eventName, fn) {
	}
}

表驱动编程

表驱动法就是一种编程模式(scheme)——从表里面查找信息而不使用逻辑语句(if 和case)。事实上,凡是能通过逻辑语句来选择的事物,都可以通过查表来选择。

应用

  • 在稳定的复杂度里绑定多个事件
// 哈希表
events:{  
   'click #app1': 'a操作''click #app2': 'b操作''click #app3': 'c操作''click #app4': 'd操作',
} 
autoBindEvents() { // 通过哈希变自动绑定事件
    for ( let key in c.events) {
        if ( c.events.hasOwnProperty(key) ) {
            const spaceIndex = key.indexOf(' ')   // 找到'click #app1'空格的数组下标
            const part1 = key.slice(0, spaceIndex) // 通过spaceIndex 分割 'click' 和 '#app1'
            const part2 = key.slice(spaceIndex + 1)
            const value = c[c.events[key]]
            v.el.on(part1, part2, value)  // 自动把多个事件绑定在一个元素上
        }
    }
}

对模块化的理解

  • 将具有相同功能的代码封装起来,当代码足够复杂时,可以根据一定规范封装成一个整块并单独放在一个文件里,并暴露出一些接口供其他模块引用。
  • 一个模块内部是私有的,模块间不能进行直接通信,需要借助EventBus做桥梁。
  • 层级结构清晰明了、可按需加载,能有效避免命名冲突
  • 可重复使用,便于维护。