一、什么是MVC
(一)MVC包括三部分,即M、V、C。
1、M:模型model用于封装与应用程序的业务逻辑相关的数据以及对数据的处理方法,会有一个或多个视图监听此模型。一旦模型的数据发生变化,模型将通知有关的视图。
2、V:视图view是它在屏幕上的表示,描绘的是model的当前状态。当模型的数据发生变化,视图相应地得到刷新自己的机会。
3、C:控制器controller定义用户界面对用户输入的响应方式,起到不同层面间的组织作用,用于控制应用程序的流程,它处理用户的行为和数据model上的改变。
import $ from 'jquery'
const m = {
data : {
n : xxx
}
}
const v = {
init(){
$('body').innerHTML = `<div>初始化n的值</div>` // 初始化HTML
},
render(){
$('body').innerHTML = `<div>更新n的值</div>` // 更新HTML
}
const c = {
init(){
v.init()
this.events()
},
events(){
$('div').on('click', function(){
console.log('在这修改n的值') // 修改n的值
render()
})
}
}
(二)M、V、C之间的联系
一千个程序员心里有一千种MVC,每个人讲的MVC都不尽相同,以下是我理解的MVC之间的关系。
当用户与view进行交互的时候,会触发view的一些事件,这些事件会被controller模块监听到,controller会根据不同的用户事件去调用model层的一些接口,通过这些接口修改model层的数据。
在之前view会通过观察者模式去观察model层的数据,如果当model层的数据改变的时候,则会通过事件通知的方式通知view层,最后view再根据新的数据改变自己的状态,也就是改变用户界面。
二、eventBus
eventBus主要用于对象间通信,eventBus允许我们在一个对象中发出一个事件,而在另一个对象中侦听该事件。eventBus 提供了 on、off 和 trigger 等 API,可以使用 on 监听事件,trigger 触发事件。使用 eventBus 可以满足最小知识原则,m 和 v 互相不知道对方的细节,但是却可以调用对方的功能。
import $ from 'jquery'
const eventBus = $({})
const m = {
data : {
n : xxx
},
update(data){
Object.assign(m.data, data)
eventBus.trigger('m updated') // 触发'm updated'
}
}
const v = {
init(){},
render(){}
}
const c = {
init(){
v.init()
eventBus.on('m updated', () => { // 监听'm updated'
v.render(m.data.n)
})
},
events(){
$('div').on('click', function(){
m.update('更新n')
})
}
}
三、表驱动编程
表驱动方法(Table-Driven Approach)是一种使你可以在表中查找信息,而不必用很多的逻辑语句(if或case)来把它们找出来的方法。事实上,任何信息都可以通过表来挑选。在简单的情况下,逻辑语句往往更简单而且更直接。
简单讲是指用查表的方法获取值。
if (key = "Key A"){
处理 Key A 相关的数据和行为。
}else if (key = "Key B"){
处理 Key B 相关的数据和行为。
}else if ... // 以此类推,处理C D E F...
上述代码可以改装成:
let hashTable = {
A: {
data: "数据1",
action: "行为1"
},
B: {
data: "数据2",
action: "行为2"
}
C:...
D:...
...
}
function handleTable(key) {
return hashTable[key]
}
console.log(handleTable('A').data)
如果继续增加C D E F … if…else…方式需要对每个数据都要单独写一句,而使用表驱动编程只需要把新的数据和行为添加到表中即可,代码复杂度更稳定。
四、模块化
(一)什么是模块
- 将一个复杂的程序依据一定的规则(规范)封装成几个块(文件), 并进行组合在一起
- 块的内部数据与实现是私有的, 只是向外部暴露一些接口(方法)与外部其它模块通信
(二)模块化
如此把各个文件封装成一个模块,只暴露一个对外的接口,HTML文件只需要导入main.js一个文件即可,不需要知道每个模块内部的细节。如下,MVC只暴露cantroller模块一个接口即可。//app1.js
import './app1.css'
import $ from 'jquery'
const m = {data : {}}
const v = {init(){}, render(){}}
const c = {
init(){
v.init()
this.events()
},
events(){
更新data
render()
}
}
export default c
//main.js
import app1 from './app1.js'
<script src='mian.js'></script>
(三)模块化的好处
- 避免命名冲突(减少命名空间污染)
- 更好的分离, 按需加载
- 更高复用性
- 高可维护性
- 符合知识最小化原则(使用的人知道的越少越好)