一、MVC是什么?
M 就是 model, 即數(shù)據(jù)模型,負(fù)責(zé)數(shù)據(jù)相關(guān)的任務(wù),包括對(duì)數(shù)據(jù)的增刪改查
V 就是view, 即視圖層,即用戶能看得到的界面
C 就是 Controller,控制器,負(fù)責(zé)監(jiān)聽用戶事件,然后調(diào)用 M 和 V 更新數(shù)據(jù)和視圖
接下來將分別用偽代碼表示三個(gè)部分的工作內(nèi)容
1.1 Model 數(shù)據(jù)模型
//示例
let Model={
data:{數(shù)據(jù)源},
create:{增加數(shù)據(jù)},
delete:{刪除數(shù)據(jù)},
update(data){
Object.assign(m.data,data) //用新數(shù)據(jù)替換舊數(shù)據(jù)
eventBus.trigger('m:update') //eventBus觸發(fā)'m:update'信息,通知View刷新界面
},
get:{獲取數(shù)據(jù)}
}
1.2 View 視圖層
//示例
let View={
el:要刷新的元素,
html:'要顯示在頁面上的刷新內(nèi)容'
init(){
v.el:初始化需要刷新的元素
},
render(){ 刷新頁面 }
}
1.3 Controller 控制器
控制器就是通過綁定事件,根據(jù)用戶的操作,調(diào)用M和V 更新數(shù)據(jù)和視圖
//示例
let Model={
data:{數(shù)據(jù)源},
create:{增加數(shù)據(jù)},
delete:{刪除數(shù)據(jù)},
update(data){
Object.assign(m.data,data)//用新數(shù)據(jù)替換舊數(shù)據(jù)
eventBus.trigger('m:update')//eventBus觸發(fā)'m:update'信息,通知View刷新界面
},
get:{獲取數(shù)據(jù)}
}
二、EventBus
2.1 EventBus是什么?
EventBus主要用于對(duì)象之間的通信,比如在上面的例子中,Model 數(shù)據(jù)模型 和View 視圖模型彼此不知道彼此的存在,但是又需要通信,于是就要用到EventBus
總結(jié):使用 eventBus 可以滿足最小知識(shí)原則,m 和 v 互相不知道對(duì)方的細(xì)節(jié),但是卻可以調(diào)用對(duì)方的功能
2.2 EventBus 有哪些API?
eventBus 提供了 on、off 和 trigger 等 API,on 用于監(jiān)聽事件,trigger 用于觸發(fā)事件
比如在上面的MVC模型中, M數(shù)據(jù)模型更新時(shí),會(huì) trigger 觸發(fā)一個(gè)事件
const m = {
....
update(data) {
Object.assign(m.data, data)
eventBus.trigger('m:updated') // 通知一下view層,我已經(jīng)更新了數(shù)據(jù),view該開始工作了
localStorage.setItem('n', m.data.n)
},
....
}
然后在controller,controller會(huì)用 on 監(jiān)聽事件, 然后通知 view 模型去重新渲染頁面
const c = {
init(container) {
v.init(container)
v.render(m.data.n) // view = render(data)
c.autoBindEvents()
eventBus.on('m:updated', () => { // controller會(huì)用 on 監(jiān)聽事件,
//然后通知 view 模型去重新渲染頁面
console.log('here')
v.render(m.data.n)
})
},
...
}
三、表驅(qū)動(dòng)編程
當(dāng)我們需要判斷3種以上的情況,做出相應(yīng)的事情,往往需要寫很多很多的If else,這樣的代碼可讀性不強(qiáng), 為了增強(qiáng)代碼的可讀性,我們可以用表驅(qū)動(dòng)編程,把用來做If條件判斷的值存進(jìn)一個(gè)哈希表,然后從表里取值:
const c = {
events: {
'click #add1': '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)
}
}
四、模塊化
模塊化就是把相對(duì)獨(dú)立的代碼從一大段代碼里抽取成一個(gè)個(gè)短小精悍的模塊
每個(gè)模塊之間相對(duì)獨(dú)立,方便以后的維護(hù)和修改
ES6的語法里引入了Import和export就是用來實(shí)現(xiàn)模塊化的
當(dāng)我們?cè)赼pp1.js 里封裝好了controller 模型, 然后導(dǎo)出controller:
export default c // 默認(rèn)導(dǎo)出
export {c} // 另外一種導(dǎo)出方式。記得要加花括號(hào)
在Main.js里我們想用controller:
import x from './app1.js'
等價(jià)于import {default as x} from './app1.js'
x.init('#app1')
關(guān)于重命名導(dǎo)出的更多例子:
// inside module.mjs
export { function1, function2 };
// inside main.mjs
import { function1 as newFunctionName,
function2 as anotherNewFunctionName } from '/modules/module.mjs';