- 美團(tuán)的前端架構(gòu)技術(shù)葉俊星的分享
- Andre staltz 的 cyle.js and functional reactive user interface 的分享
直入主題美團(tuán)前端架構(gòu)是基于 cyclejs 和 rxjs 構(gòu)建的,目標(biāo)適合復(fù)雜業(yè)務(wù)奴曙。首先我們了解一下這兩項(xiàng)技術(shù)都是什么掌腰,以及其優(yōu)勢乖阵。
最近在我的 Android 項(xiàng)目中也準(zhǔn)備應(yīng)用 MVI 來替換原有的 MVP 。 MVI 和 MVP 的不同之處就是官辽,在 MVP 中 V 也就是視圖層即負(fù)責(zé)渲染界面呈現(xiàn)給用戶线脚,又負(fù)責(zé)和用戶的交互,而在 MVI 將 V 的進(jìn)行拆分為 view 為展現(xiàn)視圖和 intent 為用戶交互塑荒。而且引入了用戶。
而且在 MVI 中也引入用戶猾普,這樣一層套一層形成循環(huán)袜炕。
我們可以將每一個環(huán)節(jié)理解為一個函數(shù)本谜,輸入是上一個環(huán)節(jié)的輸出初家,輸出是他的下一個環(huán)節(jié)的輸入。
MVI是單向流(unidirectional flow)乌助,不可變的(immutability)溜在,響應(yīng)式的,接收用戶輸入他托,通過函數(shù)轉(zhuǎn)換為特定Model(狀態(tài))掖肋,將其結(jié)果反饋給用戶(渲染界面)。我們把MVI抽象為model(), view(), intent()三個方法赏参,描述如下:
cycle.js
MVI 設(shè)計(jì)模式
如果我們把用戶和計(jì)算機(jī)看做函數(shù)志笼,
我們通過(mvi_001)
這張圖來分析人是如何機(jī)器進(jìn)行交互的呢。
首先我們將計(jì)算機(jī)和人類抽象為一樣事物把篓,也就是在交互過程中我們具有同樣功能纫溃,輸入和輸出。
- 人類:輸入是顯示器上給我們信息韧掩,輸出是鼠標(biāo)和鍵盤
- 計(jì)算機(jī):輸入是鼠標(biāo)和鍵盤轉(zhuǎn)換的指令紊浩,輸出是顯示器上像素
交互過程中是用戶和計(jì)算機(jī)形成的閉環(huán)。
進(jìn)一步抽象疗锐,我們可以將計(jì)算機(jī)和人抽象為 函數(shù)(系統(tǒng))
擴(kuò)展一下坊谁,我們?nèi)祟惪偸且詾樽约翰倏v著計(jì)算機(jī),其實(shí)我們何嘗不是被計(jì)算機(jī)所操縱呢滑臊,屏幕的信息讓我們做出相應(yīng)行為口芍。
mvp_006 輸入一個地址獲取頁面,通過需求描述
- 人 輸出地址雇卷,輸入頁面圖像
- 計(jì)算器 輸入地址字符串 輸出頁面圖像
mvp_007 我們可以輸入多個地址鬓椭,計(jì)算機(jī)會根據(jù)輸入地址返回多個頁面虹钮,這樣就形成了流,我們輸入地址時間不確定膘融,頁面返回的時間也是不確定的芙粱。都是異步所以是一個異步流
function computer(url:EventStream<String>):EventStream<screen>{
//...
}
let screenStream = computer(interactionStream)
screenStream.listen(function(ev){...})
然后我們回到用戶這邊,站在用戶角度看這件事情氧映。
我們接受電腦頁面輸入春畔,可能會根據(jù)自己需要和興趣進(jìn)行一些操作,將用戶操作看成一個交互流岛都。
我們給用戶顯示流(screenStream)就會觸發(fā)用戶一些交互流(interactionStream)
function user(screenStream:EventStream):EventStream{
//
}
- 首先會將頁面生成dom 結(jié)構(gòu)律姨,然后將Dom 渲染到物理顯示器,然后映入我們的眼里臼疫,傳遞到大腦择份,進(jìn)行語言返回到手進(jìn)行操作。
我們寫的程序主要專注 dom 和 domevent dispatcher 這兩部分內(nèi)容烫堤。
function user(screenStream:EventStream):EventStream{
screenStream.listen(function(screen)){
renderToDOM(screen)
})
document.addEventListener('*',(ev)=>{
interactionEvents.emit(ev)
})
let interactionEvents = new EventStream()
return interactionEvents
}
這里有一個交互流荣赶,就是將 DOM 上所有的事件都轉(zhuǎn)發(fā)到他身上。
let interactionStream= user(screenStream.listen) interactionStream.listen((ev)=>{...})
let screenStream= computer(interactionStream)
let interactionStream = user(screenStream)
let a = f(b)
let b = g(a)
let b = g(f(b))
let interactionStream = makeEmptyEventStream()