- M 就是 model, 即數(shù)據(jù)模型瓦戚,負責數(shù)據(jù)相關(guān)的任務(wù)挣输,包括對數(shù)據(jù)的增刪改查
- V 就是view, 即視圖層刊驴,即用戶能看得到的界面
- C 就是 Controller,控制器胸墙,負責監(jiān)聽用戶事件我注,然后調(diào)用 M 和 V 更新數(shù)據(jù)和視圖
MVC
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ù)}
}
View 視圖層
let View={
el:要刷新的元素迟隅,
html:'要顯示在頁面上的刷新內(nèi)容'
init(){
v.el:初始化需要刷新的元素
}但骨,
render(){
刷新頁面
}
}
Controller 控制器
控制器就是通過綁定事件,根據(jù)用戶的操作智袭,調(diào)用M和V 更新數(shù)據(jù)和視圖
let Controller={
init(){
v.init()//初始化View
v.render()//第一次渲染頁面
c.autoBindEvents()//自動的事件綁定
eventBus.on('m:update',()=>{v.render()}//當enentsBus觸發(fā)'m:update'是View刷新
}奔缠,
events:{事件以哈希表的方式記錄存儲},
//例如:
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})
},
method(){
data=新數(shù)據(jù)
m.update(data) // controller 通知 model去更新數(shù)據(jù)
},
autoBindEvents(){
for (let key in c.events) { // 遍歷events表,然后自動綁定事件
const value = c[c.events[key]]
const spaceIndex = key.indexOf(' ')
const part1 = key.slice(0, spaceIndex) // 拿到 'click'
const part2 = key.slice(spaceIndex + 1) // 拿到'#add1'
v.el.on(part1, part2, value)
}
}
例如做一個計算器
import './app1.css'
import $ from 'jquery'
const eventBus = $(window)
// 數(shù)據(jù)相關(guān)都放到m
const m = {
data: {
n: parseInt(localStorage.getItem('n'))
},
create() {},
delete() {},
update(data) {
Object.assign(m.data, data)
eventBus.trigger('m:updated')
localStorage.setItem('n', m.data.n)
},
get() {}
}
// 視圖相關(guān)都放到v
const v = {
el: null,
html: `
<div>
<div class="output">
<span id="number">{{n}}</span>
</div>
<div class="actions">
<button id="add1">+1</button>
<button id="minus1">-1</button>
<button id="mul2">*2</button>
<button id="divide2">÷2</button>
</div>
</div>
`,
init(container) {
v.el = $(container)
},
render(n) {
if (v.el.children.length !== 0) v.el.empty()
$(v.html.replace('{{n}}', n))
.appendTo(v.el)
}
}
// 其他都c
const c = {
init(container) {
v.init(container)
v.render(m.data.n) // view = render(data)
c.autoBindEvents()
eventBus.on('m:updated', () => {
console.log('here')
v.render(m.data.n)
})
},
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)
}
}
}
export default c
EventBus
EventBus又稱事件總線,相當于一個全局的倉庫,任何組件都可以去這個倉庫里獲取事件,主要用于對象之間的通信
EventBus有哪些API
eventBus 提供了 on妻怎、off 和 trigger 等 API,on 用于監(jiān)聽事件贬蛙,trigger 用于觸發(fā)事件
- M數(shù)據(jù)模型更新時,會 trigger 觸發(fā)一個事件
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會用 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會用 on 監(jiān)聽事件,
//然后通知 view 模型去重新渲染頁面
console.log('here')
v.render(m.data.n)
})
},
...
}
表驅(qū)動編程
- 表驅(qū)動方法是一種使你可以在表中查找信息馏臭,而不必用邏輯語句(if 或 case)來把他們找出來的方法野蝇。
- 表驅(qū)動編程的意義在于邏輯與數(shù)據(jù)的分離
function translate(term) {
if (term === '1') {
return '一'
} else if (term === '2') {
return '二'
} else if (term === '3') {
return '三'
} else {
return '?括儒?绕沈?'
}
}
// 如果想添加一個新的名詞翻譯,需要再添加一個if-else邏輯帮寻,例如:
function translate(term) {
if (term === '1') {
return '一'
} else if (term === '2') {
return '二'
} else if (term === '3') {
return '三'
} else if (term === '4') {
// 此處添加了一個新的名詞翻譯
return '四'
} else {
return '乍狐??固逗?'
}
}
這樣太麻煩了浅蚪,現(xiàn)在使用表驅(qū)動
function translate(term) {
let terms = {
'1': '一',
'2': '二',
'3': '三'
}
return terms[term];
}
// 如果想添加一個新的名詞翻譯,只需要在terms中添加一個新的表項惜傲,不需要修改整個邏輯
function translate(term) {
let terms = {
'1': '一',
'2': '二',
'3': '三'
'4': '四' // 添加一個新的名詞翻譯
}
return terms[term];
}
模塊化
就是把一大堆冗余的代碼分成一小塊一小塊的內(nèi)容,每部分相互獨立贝攒,可以使用不同的庫盗誊。
可以方便導入導出以及修改,就類似設(shè)置好了一個軟件,如果換臺機器哈踱,是不是就要重新設(shè)置荒适,模塊化就可以把內(nèi)容導出,再在新機器上導入嚣鄙。
比如:
import x from './app1.js' //導入app1.js