秦子實(shí)
摘要:在企業(yè)中臺等復(fù)雜交互場景的網(wǎng)頁應(yīng)用中,基于JSP、ASP等模板技術(shù)的頁應(yīng)用一直存在著拓展性差、修改維護(hù)困難、調(diào)試效率低下等問題。因此,對于企業(yè)中臺等復(fù)雜交互場景,需要一種能夠完全獨(dú)立于后端復(fù)雜網(wǎng)頁應(yīng)用開發(fā)方法,方法應(yīng)完全基于REST APl,且具備良好的拓展性,各功間能耦合性低,便于后期的迭代及維護(hù)。該文將以React框架為例,通過Redux控制數(shù)據(jù)狀態(tài)以代替?zhèn)鹘y(tǒng)基于模板的網(wǎng)頁開發(fā),給出一種新的獨(dú)立復(fù)雜交互式前端的開發(fā)方法。
關(guān)鍵詞:前端;JavaScript;React;Redux
中圖分類號:TP393 文獻(xiàn)標(biāo)識碼:A
文章編號:1009-3044(2020)08-0254-02
1 概述
隨著企業(yè)業(yè)務(wù)的不斷擴(kuò)展,企業(yè)中臺網(wǎng)頁應(yīng)用需要展示的報表數(shù)量越來越多,在網(wǎng)頁上進(jìn)行的數(shù)據(jù)操作越來越復(fù)雜。傳統(tǒng)基于模板的網(wǎng)頁開發(fā)(如JSP、ASP等)越來越難以應(yīng)付這些復(fù)雜功能,基于模板的網(wǎng)頁應(yīng)用由于HTML結(jié)構(gòu)以及表單提交機(jī)制等原因,不可避免地會出現(xiàn)頁面代碼臃腫,數(shù)據(jù)交換冗余較大。這不僅會占用客戶端瀏覽器資源導(dǎo)致加載緩慢.也會在請求/提交數(shù)據(jù)時大量消耗服務(wù)器資源處理無用數(shù)據(jù)。
前端框架日趨成熟,更多的企業(yè)中臺網(wǎng)頁應(yīng)用從原來的模板開發(fā),轉(zhuǎn)移到基于如React或Vue等框架的JavaScript前端網(wǎng)頁應(yīng)用。相較于模板技術(shù),前端應(yīng)用框架的核心在于狀態(tài)管理。本文以React框架為例,介紹使用Redux庫進(jìn)行前端應(yīng)用狀態(tài)管理,以實(shí)現(xiàn)具有良好擴(kuò)展性、方便修改迭代、易于調(diào)試維護(hù)的獨(dú)立前端應(yīng)用的實(shí)現(xiàn)。
2 Redux技術(shù)簡介
Redux產(chǎn)生的原因,是為了應(yīng)對功能復(fù)雜的JavaScript單頁應(yīng)用,比如在企業(yè)中臺應(yīng)用里,我們希望在同一個頁面上展示大量數(shù)據(jù),生成統(tǒng)計圖形和報表,同時也希望操作、處理這些數(shù)據(jù),使得數(shù)據(jù)實(shí)時的更新至服務(wù)器,并直接將更新結(jié)果顯示在網(wǎng)頁上。傳統(tǒng)的模板式網(wǎng)頁開發(fā)可能就需要大量的表單提交,或是采用大量各不相同的Ajax請求,這不論對于前端的網(wǎng)頁渲染,還是后端的API管理,都是非常繁雜的工作,且調(diào)試環(huán)境復(fù)雜,不易定位問題。
對于這種復(fù)雜的網(wǎng)頁應(yīng)用,Redux充分利用React等框架基于狀態(tài)(state)的頁面渲染機(jī)制,對應(yīng)用數(shù)據(jù)狀態(tài)進(jìn)行集中的、簡潔的管理。同時,Redux基于函數(shù)式編程的思想,使用冪等操作,加強(qiáng)了React等框架的狀態(tài)控制,使得網(wǎng)頁應(yīng)用的行為變得更容易追蹤、調(diào)試及后期功能拓展。
使用Redux管理應(yīng)用數(shù)據(jù)狀態(tài),無須引入額外工具或庫,僅使用JavaScript自身的JSON數(shù)據(jù)結(jié)構(gòu)以及普通的函數(shù)實(shí)現(xiàn),Redux庫本身僅有2k,利于應(yīng)用打包和發(fā)布。Redux在使用中需要注意三個原則:
1)應(yīng)用數(shù)據(jù)狀態(tài)的唯一陛,即一個網(wǎng)頁應(yīng)用有且僅有一個狀態(tài)對象。該原則不僅使得前后端數(shù)據(jù)交換更為簡潔,也能夠大幅降低應(yīng)用調(diào)試難度,有利于持續(xù)跟蹤應(yīng)用狀態(tài),加速開發(fā)流程。
2)應(yīng)用數(shù)據(jù)狀態(tài)是只讀對象,即只能夠通過發(fā)送動作(dis-patch actions)來改變該對象。該原則意味著無論應(yīng)用界面的改變或是后端返回的請求都無法直接改變該狀態(tài)對象,任何對狀態(tài)改變的期望都必須通過發(fā)送一個用于改變狀態(tài)的動作來實(shí)現(xiàn)。如此一來,Redux通過嚴(yán)格的依次執(zhí)行各個動作,實(shí)現(xiàn)了狀態(tài)變更的集中化管理,也同時實(shí)現(xiàn)了狀態(tài)的跟蹤、序列化、存儲,方便了之后的調(diào)試和測試。
3)使用冪等函數(shù)改變狀態(tài),即使用純reducer函數(shù)改變狀態(tài)。所謂冪等操作,指于狀態(tài)無關(guān)的數(shù)據(jù)操作,即無論應(yīng)用當(dāng)前處于什么狀態(tài),對同樣的輸入,一定會得到同樣的輸出。re-ducer函數(shù)的輸入為原狀態(tài)和動作,輸出為新狀態(tài)。這種設(shè)計極大地增加了應(yīng)用的拓展性,隨著應(yīng)用功能的復(fù)雜,reducer函數(shù)可以由原來的一個操作整個狀態(tài),逐漸細(xì)分為多個分別操作狀態(tài)樹的各個部分。此外,因?yàn)閞educer是純粹的冪等函數(shù),我們可以輕松地控制各reducer的執(zhí)行順序、傳遞額外數(shù)據(jù)或是進(jìn)行函數(shù)復(fù)用(如最常見的分頁操作)。
3 Redux數(shù)據(jù)狀態(tài)控制
本文以React框架為例,使用Redux對React應(yīng)用的數(shù)據(jù)狀態(tài)進(jìn)行管理。Redux的數(shù)據(jù)狀態(tài)流程如圖1所示。
3.1 存儲及狀態(tài)對象
網(wǎng)頁應(yīng)用的所有數(shù)據(jù)均維護(hù)在一個存儲(store)中,這個存儲就是數(shù)據(jù)的容器:
想要獲取當(dāng)前的數(shù)據(jù),就要對存儲進(jìn)行快照,返回的快照就是應(yīng)用當(dāng)前的狀態(tài)(state):
狀態(tài)是一個普通的JavaScript對象,用戶能夠接觸到的視圖完全取決于狀態(tài),在Redux中,狀態(tài)對象到視圖呈現(xiàn)是冪等操作,即一個確定的狀態(tài)呈現(xiàn)一個確定的視圖,而一個確定的視圖能夠推出一個確定的狀態(tài),如圖l中的S1過程。
3.2 動作對象
狀態(tài)的變化能夠引起視圖的變化,在Redux中,為了保證狀態(tài)的一致性,狀態(tài)不能被直接修改,僅能夠通過發(fā)送動作(ac-tion)對象來變更。動作是一個普通JavaScript對象,其中僅'type'屬性是必須的,表示動作的名稱,其他屬性均可自定義。例如,向視圖中的一個表格添加一行數(shù)據(jù):
動作對象通常由視圖發(fā)出,也就是用戶交在視圖上的操作期望引起狀態(tài)改變,比如在視圖的表格中點(diǎn)擊“增行”插入新的數(shù)據(jù),即圖l中的E-AI-A2過程:由視圖產(chǎn)生交互事件E(Event),進(jìn)而發(fā)送一個動作對象A1。此外,服務(wù)端返回的數(shù)據(jù)也可以通過發(fā)送動作對象引起狀態(tài)變化,比如視圖定期請求服務(wù)器獲取最新的表格數(shù)據(jù),服務(wù)器返回并渲染在視圖中,即圖1中的req-res-A2過程。
視圖和服務(wù)端要進(jìn)行多少操作,就需要產(chǎn)生有多少動作對象,我們通常會編寫一個函數(shù)用于快捷的生成這些動作,這個函數(shù)也稱作動作生成器(action creator):