1. 什么是 MVC
M(Model)数据模型,负责操作数据。
V(View)视图,负责所有的 UI 界面。
C(Controller)控制器,负责监听用户事件,然后调用 M 和 V 更新数据和页面。
//Model 示例
const Model = {
data:{数据源},
create(){增加数据},
delete(){删除数据},
update(){ //更新数据
Object.assign(m.data, data)
eventBus.trigger('m:updated')
localStorage.setItem('n', m.data.n.toString())
},
get(){读取数据}
}
//View 示例
const View = {
el: '需要展示的元素',
html: '需要展示的元素内容',
init(){
初始化需要展示的元素
}
render(){
渲染需要展示的元素
}
}
//Controller 示例
const Controller = {
init(container) {
v.init(container) //初始化View
v.render(m.data.n) //第一次渲染页面
c.autoBindEvents() //绑定事件
//事件触发时刷新页面
eventBus.on('m:updated', () => {
v.render(m.data.n)
})
},
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)
}
}
}
2. EventBus
EventBus 主要用于对象间的通信,提供了 on、off 和 trigger 等 API,on 用于监听事件,trigger 用域触发事件。使用 EventBus 可以满足最小知识原则,使得 Model 和 View 互不知道对方细节,但可以调用对方的功能。
对于上面代码,Model 在数据更新时,会使用 trigger 触发一个事件,Contrller 中回去监听这个事件,然后调用 View 重新渲染页面
const Model = {
...
update(){ //更新数据
Object.assign(m.data, data)
eventBus.trigger('m:updated') //触发事件
localStorage.setItem('n', m.data.n.toString())
},
...
}
const View = {...}
const Controller = {
init(container) {
v.init(container)
v.render(m.data.n)
c.autoBindEvents()
eventBus.on('m:updated', () => {
//事件触发时刷新页面
v.render(m.data.n)
})
},
...
}
3. 表驱动编程
表驱动方法是一种使你可以在表中查找信息,而不必用逻辑语句(if 或 case)来把他们找出来的方法。事实上,任何信息都可以通过表来挑选。在简单的情况下,逻辑语句往往更简单而且更直接。但随着逻辑链的复杂,表就变得越来越富于吸引力了。(《代码大全》)
表驱动编程可以减少重复代码,只讲重要的信息放在哈希表里,然后利用哈希表来编程,实现逻辑与数据的分离。
function translate(n) {
if (term === '1') {
return '一'
} else if (n === '2') {
return '二'
} else if (n === '3') {
return '三'
} else {
return '未知'
}
}
对于上面代码,如果想增加一个词条,就需要添加一个 if...else 结构,而使用表驱动编程,只需要添加一个新的表项,不需要修改逻辑。
function translate(n) {
let terms = {
'1': '一',
'2': '二',
'3': '三'
'4': '四' // 添加一个新的词条
}
return terms[n];
}
4. 模块化
模块化就是把大段代码中相对独立的代码抽取出来,使之成为一个个的模块。使得代码开发调试效率高,可维护性强,且避免阻断。
可使用如下代码引入和导出模块
export {a, b, c} //可以导出函数,var,let,const和类
export default randomSquare //默认导出
import $ from 'jquery' //导入默认
//等同于import {default $} from 'jquery'
重命名导入
// inside module.mjs
export { function1, function2 };
// inside main.mjs
import { function1 as newFunctionName,
function2 as anotherNewFunctionName } from '/modules/module.mjs';