一、 MVC 設(shè)計(jì)模式
1. 設(shè)計(jì)模式
- 設(shè)計(jì)模式茶敏,是通用代碼(組織方式)的一種統(tǒng)稱
2. MVC 是什么
- MVC 是三個(gè)單詞的首字母縮寫壤靶,他們分別是 Model(模型)、View(視圖)惊搏、Controller(控制器)
- MVC 認(rèn)為贮乳,程序無論是簡單還是復(fù)雜,從結(jié)構(gòu)上看都能分為三層:
- 最下層恬惯,核心的的”數(shù)據(jù)層“(Model):數(shù)據(jù)保存向拆,用于封裝與應(yīng)用程序的業(yè)務(wù)邏輯相關(guān)的數(shù)據(jù)以及對(duì)數(shù)據(jù)的處理方法
- 最上層,面向用戶的”視圖層“(View):用戶界面酪耳,它是提供給用戶的界面亲铡,描繪的是 model 的當(dāng)前狀態(tài)
- 中間層,”控制層“(Controller):業(yè)務(wù)邏輯葡兑,它處理用戶的行為和數(shù)據(jù) model 上的改變奖蔓。負(fù)責(zé)根據(jù)用戶從"視圖層"輸入的指令,選取"數(shù)據(jù)層"中的數(shù)據(jù)讹堤,然后對(duì)其進(jìn)行相應(yīng)的操作吆鹤,產(chǎn)生最終結(jié)果
- 這三層緊密聯(lián)系在一起,但又是互相獨(dú)立的洲守,每一層內(nèi)部的變化不影響其他層疑务。每一層都對(duì)外提供接口供調(diào)用沾凄。這樣一來,軟件就可以實(shí)現(xiàn)模塊化知允,修改外觀或者變更數(shù)據(jù)都不用修改其他層撒蟀,大大方便了維護(hù)和升級(jí),提高靈活性和復(fù)用性
二温鸽、MVC 實(shí)例
比如以一個(gè)實(shí)現(xiàn)加減乘除的簡易計(jì)算機(jī)為例
1. Model 數(shù)據(jù)模型
- 定義并封裝數(shù)據(jù)以及數(shù)據(jù)的處理方法
let Model={
data:{}, // 數(shù)據(jù)源
create:{}, // 增加數(shù)據(jù)
delete:{}, //刪除數(shù)據(jù)
update(data){}, // 更新數(shù)據(jù)
get:{} // 獲取數(shù)據(jù)
}
2. View 視圖
- 定義和封裝渲染到頁面的元素和渲染方法
let View={
el, // 要渲染的元素
html, // 要顯示在頁面上的渲染內(nèi)容
init(){
v.el // 初始化需要渲染的元素
},
render(){} // 渲染頁面
}
3. Controller 控制器
- 根據(jù)用戶的行為保屯,更新數(shù)據(jù)和視圖
let Controller={
init(){}, // 初始化渲染頁面
events: {}, // 事件
// 點(diǎn)擊事件的實(shí)現(xiàn)
add(){},
minus() {},
mul(){},
div(){},
autoBindEvents(){} // 綁定事件
}
三、 發(fā)布/訂閱
JS 中事件完全可以理解成“信號(hào)”涤垫,如果存在一個(gè)“信號(hào)中心”姑尺,某個(gè)任務(wù)執(zhí)行完成,就向信號(hào)中心“發(fā)布”一個(gè)信號(hào)蝠猬,其他任務(wù)可以向信號(hào)中心“訂閱”這個(gè)信號(hào)切蟋,從而知道什么時(shí)候自己可以開始執(zhí)行,這就叫做”發(fā)布/訂閱模式”榆芦,又稱“觀察者模式”
// f2 向信號(hào)中心 jQuery 訂閱 done 信號(hào)
jQuery.subscribe('done', f2)
// f1 執(zhí)行完成后柄粹,向信號(hào)中心 jQuery 發(fā)布 done 信號(hào),從而引發(fā) f2 的執(zhí)行
function f1() {
setTimeout(function () {
// ...
jQuery.publish('done')
}, 1000)
}
// f2 完成執(zhí)行后匆绣,可以取消訂閱
jQuery.unsubscribe('done', f2)
這種方法的性質(zhì)與“事件監(jiān)聽”類似镰惦,但是明顯優(yōu)于后者。因?yàn)榭梢酝ㄟ^查看“消息中心”犬绒,了解存在多少信號(hào)旺入、每個(gè)信號(hào)有多少訂閱者,從而監(jiān)控程序的運(yùn)行
四凯力、 EventBus
EventBus茵瘾,也稱為事件總線,在 JS 是一種對(duì)象或組件的通信方式咐鹤,是發(fā)布訂閱模式的一種具體實(shí)現(xiàn)
可以利用 EventBus 原生的on()
拗秘、off()
、trigger()/emit()
API 來發(fā)布訂閱祈惶、取消訂閱雕旨、觸發(fā)
如何理解 EventBus 呢
- 用一個(gè)十分淺顯的例子,Bus 即公交車捧请,城市中的公交車的是怎么運(yùn)作的呢凡涩?
公交車會(huì)在城市中按照既定的路線一遍遍的循環(huán)。乘客上車之后會(huì)跟公交車司機(jī)說一下”我在第二站疹蛉,下車“活箕,于是等公交車到了第二站后,會(huì)提醒乘客”第二站到了可款,請(qǐng)下車“育韩,如果乘客中途改變了注意也會(huì)告訴司機(jī)”我第二站不下車了克蚂,后面的站再下車“。 - EventBus 是怎么運(yùn)行的呢筋讨?
相應(yīng)的埃叭,EventBus 對(duì)象會(huì)在 JS 線程中一遍一遍的循環(huán)。它是一個(gè)訂閱中心悉罕,比如你向起訂閱一個(gè)點(diǎn)擊事件EventBus.on('click')
赤屋,當(dāng)事件觸發(fā)時(shí) EventBus 會(huì)執(zhí)行你添加的事件監(jiān)聽函數(shù)EventBus.emit('click')
,如果想取消訂閱可以EventBus.off('click')
來取消訂閱 - 事實(shí)上蛮粮,我們?cè)谑褂?JS 綁定事件監(jiān)聽函數(shù),都是在使用發(fā)布訂閱模式
五谜慌、表驅(qū)動(dòng)編程
我們?cè)诰幊踢^程中然想,免不了會(huì)遇到需要判斷多種條件的情況,這種時(shí)候如果使用 if...else欣范、switch 語句变泄,寫出的代碼就會(huì)出現(xiàn)可讀性較差甚至出現(xiàn)錯(cuò)誤,如果我們使用表驅(qū)動(dòng)編程的方式就會(huì)是代碼可讀性增強(qiáng)并且不容易出錯(cuò)恼琼。
- 淺顯易懂的例子
const day = new Date().getDay()
let day_zh;
if(day === 0){
day_zh = '星期日'
}else if(day === 1) {
day_zh = '星期一'
}
...
else{
day_zh = '星期六'
}
// 或者 用 switch case
switch(day) {
case 0:
day_zh = '星期日'
break;
case 1:
day_zh = '星期一'
break;
...
}
// 使用表驅(qū)動(dòng)的方式
const week = ['星期日', '星期一',..., '星期六']
const day = new Date().getDay(
const day_zh = week[day]
六妨蛹、模塊化
- 模塊化就是把功能相對(duì)獨(dú)立的代碼從一大段代碼里封裝成一個(gè)個(gè)短小精悍的模塊
- 每個(gè)模塊之間相對(duì)獨(dú)立,每個(gè)模塊的修改不會(huì)影響其他模塊的功能晴竞,甚至不同模塊之間使用不同的技術(shù)實(shí)現(xiàn)也不會(huì)帶來影響
- ES6的語法里使用 Import 和 export 語法來實(shí)現(xiàn) JS 代碼的模塊化