一思杯、CMS管理系統(tǒng)功能
CMS是ContentManagementSystem的縮寫胜蛉,意為"內(nèi)容管理系統(tǒng)"。
CMS都有可能包括些什么色乾?
隱藏在內(nèi)容管理系統(tǒng)(CMS)之后的基本思想是分離內(nèi)容的管理和設(shè)計(jì)誊册。頁(yè)面設(shè)計(jì)存儲(chǔ)在模板里,而內(nèi)容存儲(chǔ)在數(shù)據(jù)庫(kù)或獨(dú)立的文件中暖璧。 當(dāng)一個(gè)用戶請(qǐng)求頁(yè)面時(shí)案怯,各部分聯(lián)合生成一個(gè)標(biāo)準(zhǔn)的HTML(標(biāo)準(zhǔn)通用標(biāo)記語(yǔ)言下的一個(gè)應(yīng)用)頁(yè)面。
一個(gè)內(nèi)容管理系統(tǒng)通常有如下要素:
文檔模板
腳本語(yǔ)言或標(biāo)記語(yǔ)言
與數(shù)據(jù)庫(kù)集成
內(nèi)容管理系統(tǒng)也簡(jiǎn)化了網(wǎng)站的內(nèi)容供給和內(nèi)容管理的責(zé)任委托澎办。很多內(nèi)容管理系統(tǒng)允許對(duì)網(wǎng)站的不同層面人員賦予不同等級(jí)的訪問(wèn)權(quán)限嘲碱, 這使得他們不必研究操作系統(tǒng)級(jí)的權(quán)限設(shè)置,只需用瀏覽器接口即可完成浮驳。
內(nèi)容管理系統(tǒng)被分離成以下幾個(gè)層面:各個(gè)層面優(yōu)先考慮的需求不同
1悍汛,后臺(tái)業(yè)務(wù)子系統(tǒng)管理(管理優(yōu)先:內(nèi)容管理):新聞錄入系統(tǒng),全文檢索子系統(tǒng)等至会,針對(duì)不同系統(tǒng)的方便管理者的內(nèi)容錄入:所見即所得的編輯管理界面等离咐,清晰的業(yè)務(wù)邏輯:各種子系統(tǒng)的權(quán)限控制機(jī)制等;
2奉件,前臺(tái)發(fā)布(效率優(yōu)先:發(fā)布管理):面向最終用戶的緩存發(fā)布
可以通過(guò)WEB實(shí)現(xiàn)一套完整的CMS管理系統(tǒng)宵蛀,用于對(duì)PC網(wǎng)站和移動(dòng)端瀏覽內(nèi)容的增、刪县貌、改术陶、查等操作,通過(guò)對(duì)模板內(nèi)容的修改即可改變網(wǎng)頁(yè)展示內(nèi)容煤痕,方便了網(wǎng)站管理人員的日常管理和操作梧宫。
二接谨、One Page One Application
1.定義
One Page, One Application(后面縮寫為OPOA,或者1P1A)塘匣, 含義很簡(jiǎn)單:一個(gè)頁(yè)面就是一個(gè)應(yīng)用脓豪。不再使用iframe, 頁(yè)面提交不能再使用submit方式。網(wǎng)頁(yè)中發(fā)生的操作和交互都在當(dāng) 前頁(yè)面進(jìn)行忌卤。
在
眾多的基于Web的MIS系統(tǒng)中扫夜,沒有人關(guān)心頁(yè)面的組織形式;大多數(shù)稍微復(fù)雜的MIS系統(tǒng)驰徊,都采用分禎(Frame)的方式來(lái)組織頁(yè)面笤闯,這樣,在進(jìn)行業(yè)務(wù)
操作的時(shí)候棍厂,url的變化表現(xiàn)在一個(gè)框架頁(yè)面內(nèi)颗味,從瀏覽器的地址看起來(lái),只有一個(gè)地址勋桶;更有甚者脱衙,一些應(yīng)用干脆彈出一個(gè)去掉了瀏覽器菜單、工具條例驹、地址
欄捐韩、狀態(tài)欄的窗口(比如招商銀行、民生銀行的網(wǎng)上銀行系統(tǒng))鹃锈,連地址都看不見荤胁。因此,一個(gè)頁(yè)面就是一個(gè)應(yīng)用屎债,從用戶的角度來(lái)說(shuō)仅政,對(duì)于操作型系統(tǒng),是一種非
常自然的體現(xiàn)盆驹。用戶無(wú)需了解每一個(gè)具體的操作對(duì)應(yīng)的地址是什么圆丹。
這種設(shè)計(jì)背后的含義實(shí)際是:是希
望由程序來(lái)控制用戶的行為,還是反過(guò)來(lái)躯喇。在操作型系統(tǒng)中辫封,每一步的操作往往被業(yè)務(wù)含義嚴(yán)格定義,無(wú)論是應(yīng)用的設(shè)計(jì)者廉丽,還是其使用者倦微,都希望在一種受控的狀
況下來(lái)進(jìn)行操作。例如正压,一個(gè)審批動(dòng)作欣福,用戶更希望是通過(guò)一個(gè)按鈕來(lái)觸發(fā),而不是訪問(wèn)類似于/approve.action?itemid=123的方式焦履。
這樣的好處是:很多東西拓劝,例如:JS雏逾,CSS,HEAD等整個(gè)系統(tǒng)都只需加載一次郑临。加快響應(yīng)速度校套。客戶體驗(yàn)也有所提高牧抵,不再?gòu)棾龃翱冢辉僬麄€(gè)頁(yè)面進(jìn)行刷新侨把。
2.場(chǎng)景(內(nèi)容管理系統(tǒng)更傾向明確的URL定位頁(yè)面)
顯然犀变,OPOA的設(shè)計(jì)只能針對(duì)那些對(duì)URL不敏感的系統(tǒng),或者說(shuō)操作型系統(tǒng)秋柄。絕大多數(shù)MIS系統(tǒng)都屬于這一范疇获枝,Email系統(tǒng)也是這一范
疇,其他領(lǐng)域骇笔,如監(jiān)控系統(tǒng)省店,聊天室等都可以采用這種思路。反面的例子是笨触,對(duì)于內(nèi)容型系統(tǒng)懦傍,如新聞系統(tǒng),Blog系統(tǒng)芦劣,論壇系統(tǒng)粗俱,用戶更希望能夠通過(guò)一個(gè)明
確的URL來(lái)定位頁(yè)面內(nèi)容,搜索引擎也喜歡這種地址虚吟。這種應(yīng)用需要的是一個(gè)合理寸认,易懂,明確的地址串慰。
3.設(shè)計(jì)與實(shí)現(xiàn)
注意到上述的OPOA地實(shí)現(xiàn)只是對(duì)用戶而言偏塞,看起來(lái)好像是一個(gè)頁(yè)面一樣,但實(shí)際上還是有眾多的action邦鲫, page在后面工作灸叼。
三、react的技術(shù)準(zhǔn)備
1.react的起源
React 起源于 Facebook 的內(nèi)部項(xiàng)目掂碱,意在解決隨時(shí)間數(shù)據(jù)不斷變化的大規(guī)模應(yīng)用程序開發(fā)怜姿,react可以表現(xiàn)出應(yīng)用程序在任何時(shí)間點(diǎn)的樣子,底層數(shù)據(jù)改變時(shí)疼燥,react的虛擬DOM機(jī)制會(huì)自動(dòng)重新渲染沧卢,更新界面。
2.對(duì)react的認(rèn)識(shí)
React不是一個(gè)完整的MVC框架醉者,最多可以認(rèn)為是MVC中的V(View)但狭,甚至React并不非常認(rèn)可MVC開發(fā)模式披诗;
React的服務(wù)器端Render能力只能算是一個(gè)錦上添花的功能,并不是其核心出發(fā)點(diǎn)立磁,事實(shí)上React官方站點(diǎn)幾乎沒有提及其在服務(wù)器端的應(yīng)用呈队;
React的虛擬DOM原理:在Web開發(fā)中,我們總需要將變化的數(shù)據(jù)實(shí)時(shí)反應(yīng)到UI上唱歧,這時(shí)就需要對(duì)DOM進(jìn)行操作宪摧。而復(fù)雜或頻繁的DOM操作通常是性能瓶頸產(chǎn)生的原因(如何進(jìn)行高性能的復(fù)雜DOM操作通常是衡量一個(gè)前端開發(fā)人員技能的重要指標(biāo))。React為此引入了虛擬DOM(Virtual DOM)的 機(jī)制:在瀏覽器端用Javascript實(shí)現(xiàn)了一套DOM API颅崩〖赣冢基于React進(jìn)行開發(fā)時(shí)所有的DOM構(gòu)造都是通過(guò)虛擬DOM進(jìn)行,每當(dāng)數(shù)據(jù)變化時(shí)沿后,React都會(huì)重新構(gòu)建整個(gè)DOM樹沿彭,然后React將當(dāng)前 整個(gè)DOM樹和上一次的DOM樹進(jìn)行對(duì)比,得到DOM結(jié)構(gòu)的區(qū)別尖滚,然后僅僅將需要變化的部分進(jìn)行實(shí)際的瀏覽器DOM更新喉刘。而且React能夠批處理虛擬 DOM的刷新,在一個(gè)事件循環(huán)(Event Loop)內(nèi)的兩次數(shù)據(jù)變化會(huì)被合并漆弄,例如你連續(xù)的先將節(jié)點(diǎn)內(nèi)容從A變成B睦裳,然后又從B變成A,React會(huì)認(rèn)為UI不發(fā)生任何變化撼唾,而如果通過(guò)手動(dòng)控制推沸,這種邏輯通常是極其復(fù)雜的。盡管每一次都需要構(gòu)造完整的虛擬DOM樹券坞,但是因?yàn)樘摂MDOM是內(nèi)存數(shù)據(jù)鬓催,性能是極高的,而對(duì)實(shí)際DOM進(jìn)行操作的僅僅是 Diff部分恨锚,因而能達(dá)到提高性能的目的宇驾。這樣,在保證性能的同時(shí)猴伶,開發(fā)者將不再需要關(guān)注某個(gè)數(shù)據(jù)的變化如何更新到一個(gè)或多個(gè)具體的DOM元素课舍,而只需要 關(guān)心在任意一個(gè)數(shù)據(jù)狀態(tài)下,整個(gè)界面是如何Render的他挎。
jsx語(yǔ)法:HTML 語(yǔ)言直接寫在 JavaScript 語(yǔ)言之中筝尾,不加任何引號(hào),這就是 JSX 的語(yǔ)法办桨,它允許 HTML 與 JavaScript 的混寫筹淫。React不是一個(gè)新的模板語(yǔ)言,JSX只是一個(gè)表象呢撞,沒有JSX的React也能工作损姜。jsx語(yǔ)法與javascript并不兼容饰剥,需要通過(guò)babel-loader來(lái)解析。
組件化:構(gòu)建可組合的組件(組件:對(duì)數(shù)據(jù)和方法的簡(jiǎn)單封裝摧阅,封裝起來(lái)的具有獨(dú)立功能的UI部件)汰蓉,是代碼復(fù)用、測(cè)試和關(guān)注分離棒卷。React推薦以組件的方式去重新思考UI構(gòu)成顾孽,將UI上每一個(gè)功能相對(duì)獨(dú)立的模塊定義 成組件,然后將小的組件通過(guò)組合或者嵌套的方式構(gòu)成大的組件比规,最終完成整體UI的構(gòu)建岩齿。MVC的思想讓你做到視圖-數(shù)據(jù)-控制器的分離,那么組件化的思考方式則是帶來(lái)了UI功能模塊之間的分離苞俘。
React認(rèn)為一個(gè)組件應(yīng)該具有如下特征:
(1)可組合(Composeable):一個(gè)組件易于和其它組件一起使用,或者嵌套在另一個(gè)組件內(nèi)部龄章。如果一個(gè)組件內(nèi)部創(chuàng)建了另一個(gè)組件吃谣,那么說(shuō)父組件擁有(own)它創(chuàng)建的子組件,通過(guò)這個(gè)特性做裙,一個(gè)復(fù)雜的UI可以拆分成多個(gè)簡(jiǎn)單的UI組件岗憋;
(2)可重用(Reusable):每個(gè)組件都是具有獨(dú)立功能的,它可以被使用在多個(gè)UI場(chǎng)景锚贱;
(3)可維護(hù)(Maintainable):每個(gè)小的組件僅僅包含自身的邏輯仔戈,更容易被理解和維護(hù);
3.ReactJS組件
組件屬性
前面說(shuō)了拧廊,ReactJS是基于組件化的開發(fā)监徘,下面我們開始來(lái)學(xué)習(xí)
ReactJS里面的組件,React 允許將代碼封裝成組件(component)吧碾,然后像插入普通 HTML
標(biāo)簽一樣凰盔,在網(wǎng)頁(yè)中插入這個(gè)組件。React.createClass 方法就用于生成一個(gè)組件類倦春。
1)獲取屬性的值用的是this.props.屬性名
2)創(chuàng)建的組件名稱首字母必須大寫户敬。
3)為元素添加css的class時(shí),要用className睁本。
4)組件的style屬性的設(shè)置方式也值得注意尿庐,要寫成style={{width: this.state.witdh}}。
組件狀態(tài)
組 件免不了要與用戶互動(dòng)呢堰,React 的一大創(chuàng)新抄瑟,就是將組件看成是一個(gè)狀態(tài)機(jī),一開始有一個(gè)初始狀態(tài)枉疼,然后用戶互動(dòng)锐借,導(dǎo)致狀態(tài)變化问麸,從而觸發(fā)重新渲染 UI 。當(dāng)用戶點(diǎn)擊組件钞翔,導(dǎo)致狀態(tài)變化严卖,this.setState 方法就修改狀態(tài)值,每次修改以后布轿,自動(dòng)調(diào)用 this.render 方法哮笆,再次渲染組件。
組件的生命周期
組件的生命周期分成三個(gè)狀態(tài):
Mounting:已插入真實(shí) DOM
Updating:正在被重新渲染
Unmounting:已移出真實(shí) DOM
React 為每個(gè)狀態(tài)都提供了兩種處理函數(shù)汰扭,will 函數(shù)在進(jìn)入狀態(tài)之前調(diào)用稠肘,did 函數(shù)在進(jìn)入狀態(tài)之后調(diào)用,三種狀態(tài)共計(jì)五種處理函數(shù)萝毛。
componentWillMount()
componentDidMount()
componentWillUpdate(object nextProps, object nextState)
componentDidUpdate(object prevProps, object prevState)
componentWillUnmount()
組件的嵌套
React是基于組件化的開發(fā)项阴,那么組件化開發(fā)最大的優(yōu)點(diǎn)是什么?毫無(wú)疑問(wèn)笆包,當(dāng)然是復(fù)用环揽,下面我們來(lái)看看React中到底是如何實(shí)現(xiàn)組件的復(fù)用的,這里我們還寫一個(gè)例子來(lái)說(shuō)吧庵佣,代碼如下:
這里我們創(chuàng)建了一個(gè)Search組件歉胶,然后又創(chuàng)建了一個(gè)Page組件,然后我們?cè)赑age組件中調(diào)用Search組件巴粪,并且調(diào)用了兩次通今,這里我們通過(guò)屬性searchType傳入值。
4.ReactJS小結(jié)
關(guān)于ReactJS今天就先學(xué)習(xí)到這里了肛根,下面來(lái)總結(jié)一下辫塌,主要有以下幾點(diǎn):
1、ReactJs是基于組件化的開發(fā)派哲,所以最終你的頁(yè)面應(yīng)該是由若干個(gè)小組件組成的大組件璃氢。
2、可以通過(guò)屬性狮辽,將值傳遞到組件內(nèi)部一也,同理也可以通過(guò)屬性將內(nèi)部的結(jié)果傳遞到父級(jí)組件(留給大家研究);要對(duì)某些值的變化做DOM操作的喉脖,要把這些值放到state中椰苟。
3、
為組件添加外部css樣式時(shí)树叽,類名應(yīng)該寫成className而不是class;添加內(nèi)部樣式時(shí)舆蝴,應(yīng)該是style={{opacity:
this.state.opacity}}而不是style="opacity:{this.state.opacity};"。
4、組件名稱首字母必須大寫洁仗。
5层皱、變量名用{}包裹,且不能加雙引號(hào)赠潦。
react相關(guān)資源:https://github.com/simongfxu/simongfxu.github.com/issues/21
5.ReactJS+Flux開發(fā)模式
react不是一個(gè)完整的jsMVC開發(fā)框架叫胖,僅僅可以充當(dāng)View層。所有的react組件輸出的只是HTML她奥,不能單獨(dú)使用react創(chuàng)建一個(gè)完整的動(dòng)態(tài)應(yīng)用瓮增。react不包含:
事件系統(tǒng)(除了原生DOM事件)
Ajax功能
數(shù)據(jù)層
這種開發(fā)模式下需要的幾個(gè)要素:
Flux:用于管理數(shù)據(jù)流,描述單向數(shù)據(jù)流哩俭,只有從模型到視圖的數(shù)據(jù)流動(dòng)绷跑,定義組件之間,組件和數(shù)據(jù)模型之間如何通信凡资。且包含某些特定的事件和監(jiān)聽器砸捏,dispacher和某個(gè)js事件庫(kù)。
dispacher本質(zhì)是一個(gè)事件系統(tǒng)隙赁,全局的分發(fā)器垦藏,負(fù)責(zé)廣播和注冊(cè)callback,有且只有一個(gè)全局的dispacher鸳谜。
Store:可以存在多個(gè)Store存儲(chǔ)不同數(shù)據(jù)類型,用于響應(yīng)dispacher事件式廷,并且進(jìn)行響應(yīng)的數(shù)據(jù)處理咐扭,是應(yīng)用中唯一知道如何更新數(shù)據(jù)的地方,只有store可以注冊(cè)callback滑废。View永遠(yuǎn)不應(yīng)該調(diào)用App.Dispatcher.register蝗肪,Dispatcher的存在就是為了將消息從View傳遞到Store,然后Store觸發(fā)change事件蠕趁,通過(guò)第三方j(luò)s事件傳遞到View薛闪。
參考資料
https://zhuanlan.zhihu.com/p/19900243
6.ReactJS+Redux開發(fā)模式
Redux 是 JavaScript 狀態(tài)容器,提供可預(yù)測(cè)化的狀態(tài)管理俺陋。 可以讓你構(gòu)建一致化的應(yīng)用豁延,運(yùn)行于不同的環(huán)境(客戶端、服務(wù)器腊状、原生應(yīng)用)诱咏,并且易于測(cè)試。Redux 除了和React一起用外缴挖,還支持其它界面庫(kù)袋狞。Redux 由Flux演變而來(lái),但受Elm的啟發(fā),避開了 Flux 的復(fù)雜性苟鸯。
要點(diǎn)
應(yīng)用中所有的 state 都以一個(gè)對(duì)象樹的形式儲(chǔ)存在一個(gè)單一的store中同蜻。
惟一改變 state 的辦法是觸發(fā)action,一個(gè)描述發(fā)生什么的對(duì)象早处。
為了描述 action 如何改變 state 樹湾蔓,需要編寫reducers。
action:應(yīng)該把要做的修改變成一個(gè)普通對(duì)象陕赃,這個(gè)對(duì)象被叫做action卵蛉,而不是直接修改 state,action中定義action純函數(shù)么库,所有的邏輯和數(shù)據(jù)處理在action函數(shù)中進(jìn)行傻丝,包括數(shù)據(jù)接口請(qǐng)求,export特定的action事件名稱诉儒,action對(duì)象中葡缰,type為約定的事件名,其他參數(shù)可以自定義忱反。
reducer:編寫專門的函數(shù)來(lái)決定每個(gè) action 如何改變應(yīng)用的 state泛释,這個(gè)函數(shù)被叫做reducer。import約定好的action事件名稱温算,根據(jù)不同的action.type,然后返回不同的新state對(duì)象怜校,數(shù)據(jù)均來(lái)自action對(duì)象。
相比
Flux注竿,只需要注意一個(gè)重要的區(qū)別茄茁。Redux 沒有 Dispatcher 且不支持多個(gè) store。相反巩割,只有一個(gè)單一的 store
和一個(gè)根級(jí)的 reduce 函數(shù)(reducer)裙顽。隨著應(yīng)用不斷變大,你應(yīng)該把根級(jí)的 reducer 拆成多個(gè)小的
reducers宣谈,分別獨(dú)立地操作 state 樹的不同部分愈犹,而不是添加新的 stores。這就像一個(gè) React
應(yīng)用只有一個(gè)根級(jí)的組件闻丑,這個(gè)根組件又由很多小組件構(gòu)成漩怎。
三大原則
Redux 可以用這三個(gè)基本原則來(lái)描述:
單一數(shù)據(jù)源
整個(gè)應(yīng)用的state被儲(chǔ)存在一棵 object tree 中,并且這個(gè) object tree 只存在于唯一一個(gè)store中嗦嗡。
State 是只讀的
惟一改變 state 的方法就是觸發(fā)action扬卷,action 是一個(gè)用于描述已發(fā)生事件的普通對(duì)象。使用純函數(shù)來(lái)執(zhí)行修改
為了描述 action 如何改變 state tree 酸钦,你需要編寫reducers怪得。
Reducer
只是一些純函數(shù)咱枉,它接收先前的 state 和 action,并返回新的 state徒恋。剛開始你可以只有一個(gè)
reducer蚕断,隨著應(yīng)用變大,你可以把它拆成多個(gè)小的 reducers入挣,分別獨(dú)立地操作 state tree 的不同部分亿乳,因?yàn)?reducer
只是函數(shù),你可以控制它們被調(diào)用的順序径筏,傳入附加數(shù)據(jù)葛假,甚至編寫可復(fù)用的 reducer 來(lái)處理一些通用任務(wù)
與Flux比較
Redux
的靈感來(lái)源于 Flux 的幾個(gè)重要特性。和 Flux 一樣滋恬,Redux 規(guī)定聊训,將模型的更新邏輯全部集中于一個(gè)特定的層(Flux 里的
store,Redux 里的 reducer)恢氯。Flux 和 Redux 都不允許程序直接修改數(shù)據(jù)带斑,而是用一個(gè)叫作 “action”
的普通對(duì)象來(lái)對(duì)更改進(jìn)行描述。
而不同于 Flux 勋拟,Redux 并沒有 dispatcher 的概念勋磕。原因是它依賴純函數(shù)來(lái)替代事件處理器。純函數(shù)構(gòu)建簡(jiǎn)單敢靡,也不需額外的實(shí)體來(lái)管理它們挂滓。你可以將這點(diǎn)看作這兩個(gè)框架的差異或細(xì)節(jié)實(shí)現(xiàn),取決于你怎么看 Flux啸胧。Flux 常常被表述為(state, action) => state赶站。從這個(gè)意義上說(shuō),Redux 無(wú)疑是 Flux 架構(gòu)的實(shí)現(xiàn)吓揪,且得益于純函數(shù)而更為簡(jiǎn)單亲怠。
和 Flux 的另一個(gè)重要區(qū)別所计,是Redux 設(shè)想你永遠(yuǎn)不會(huì)變動(dòng)你的數(shù)據(jù)柠辞。你可以很好地使用普通對(duì)象和數(shù)組來(lái)管理 state ,而不是在多個(gè) reducer 里變動(dòng)數(shù)據(jù)主胧。正確且簡(jiǎn)便的方式是叭首,你應(yīng)該在 reducer 中返回一個(gè)新對(duì)象來(lái)更新 state, 同時(shí)配合object spread 運(yùn)算符提案或一些庫(kù)踪栋,如Immutable焙格。
雖然出于性能方面的考慮,寫不純的 reducer來(lái)變動(dòng)數(shù)據(jù)在技術(shù)上是可行的夷都,但我們并不鼓勵(lì)這么做眷唉。不純的 reducer 會(huì)使一些開發(fā)特性,如時(shí)間旅行、記錄/回放或熱加載不可實(shí)現(xiàn)冬阳。此外蛤虐,在大部分實(shí)際應(yīng)用中,這種數(shù)據(jù)不可變動(dòng)的特性并不會(huì)帶來(lái)性能問(wèn)題肝陪,就像Om所表現(xiàn)的驳庭,即使對(duì)象分配失敗,仍可以防止昂貴的重渲染和重計(jì)算氯窍。而得益于 reducer 的純度饲常,應(yīng)用內(nèi)的變化更是一目了然。
Action
首先狼讨,讓我們來(lái)給 action 下個(gè)定義贝淤。
Action是把數(shù)據(jù)從應(yīng)用(譯者注:這里之所以不叫 view 是因?yàn)檫@些數(shù)據(jù)有可能是服務(wù)器響應(yīng),用戶輸入或其它非 view 的數(shù)據(jù) )傳到 store 的有效載荷熊楼。它是 store 數(shù)據(jù)的唯一來(lái)源霹娄。一般來(lái)說(shuō)你會(huì)通過(guò)store.dispatch()將 action 傳到 store。
Action 本質(zhì)上是 JavaScript 普通對(duì)象鲫骗。我們約定犬耻,action 內(nèi)必須使用一個(gè)字符串類型的type字段來(lái)表示將要執(zhí)行的動(dòng)作。多數(shù)情況下执泰,type會(huì)被定義成字符串常量枕磁。當(dāng)應(yīng)用規(guī)模越來(lái)越大時(shí),建議使用單獨(dú)的模塊或文件來(lái)存放 action术吝。
除了type字段外计济,action 對(duì)象的結(jié)構(gòu)完全由你自己決定。參照Flux 標(biāo)準(zhǔn) Action獲取關(guān)于如何構(gòu)造 action 的建議排苍。
這時(shí)沦寂,我們還需要再添加一個(gè) action type 來(lái)表示用戶完成任務(wù)的動(dòng)作。因?yàn)閿?shù)據(jù)是存放在數(shù)組中的淘衙,所以我們通過(guò)下標(biāo)index來(lái)引用特定的任務(wù)传藏。而實(shí)際項(xiàng)目中一般會(huì)在新建數(shù)據(jù)的時(shí)候生成唯一的 ID 作為數(shù)據(jù)的引用標(biāo)識(shí)。
我們應(yīng)該盡量減少在 action 中傳遞的數(shù)據(jù)彤守。比如上面的例子毯侦,傳遞index就比把整個(gè)任務(wù)對(duì)象傳過(guò)去要好。
Action 創(chuàng)建函數(shù)
Action 創(chuàng)建函數(shù)就是生成 action 的方法具垫〕蘩耄“action” 和 “action 創(chuàng)建函數(shù)” 這兩個(gè)概念很容易混在一起,使用時(shí)最好注意區(qū)分筝蚕。這樣做將使 action 創(chuàng)建函數(shù)更容易被移植和測(cè)試卦碾。
Reducer
Action只是描述了有事情發(fā)生了這一事實(shí)铺坞,并沒有指明應(yīng)用如何更新 state。而這正是 reducer 要做的事情洲胖。
設(shè)計(jì) State 結(jié)構(gòu)
在 Redux 應(yīng)用中康震,所有的 state 都被保存在一個(gè)單一對(duì)象中。建議在寫代碼前先想一下這個(gè)對(duì)象的結(jié)構(gòu)宾濒。如何才能以最簡(jiǎn)的形式把應(yīng)用的 state 用對(duì)象描述出來(lái)腿短?
以 todo 應(yīng)用為例,需要保存兩種不同的數(shù)據(jù):
當(dāng)前選中的任務(wù)過(guò)濾條件绘梦;
完整的任務(wù)列表议忽。
通常握截,這個(gè) state 樹還需要存放其它一些數(shù)據(jù)吝镣,以及一些 UI 相關(guān)的 state庐船。這樣做沒問(wèn)題,但盡量把這些數(shù)據(jù)與 UI 相關(guān)的 state 分開榄棵。
Action 處理
現(xiàn)在我們已經(jīng)確定了 state 對(duì)象的結(jié)構(gòu)凝颇,就可以開始開發(fā) reducer。reducer 就是一個(gè)純函數(shù)疹鳄,接收舊的 state 和 action拧略,返回新的 state。
之所以稱作 reducer 是因?yàn)樗鼘⒈粋鬟f給Array.prototype.reduce(reducer, ?initialValue)方法瘪弓。保持 reducer 純凈非常重要垫蛆。永遠(yuǎn)不要在 reducer 里做這些操作:
修改傳入?yún)?shù);
執(zhí)行有副作用的操作腺怯,如 API 請(qǐng)求和路由跳轉(zhuǎn)袱饭;
調(diào)用非純函數(shù),如Date.now()或Math.random()呛占。
現(xiàn)在只需要謹(jǐn)記 reducer 一定要保持純凈虑乖。只要傳入?yún)?shù)相同,返回計(jì)算得到的下一個(gè) state 就一定相同晾虑。沒有特殊情況疹味、沒有副作用,沒有 API 請(qǐng)求走贪、沒有變量修改佛猛,單純執(zhí)行計(jì)算惑芭。
明白了這些之后坠狡,就可以開始編寫 reducer,并讓它來(lái)處理之前定義過(guò)的action遂跟。
我們將以指定 state 的初始狀態(tài)作為開始逃沿。Redux 首次執(zhí)行時(shí)婴渡,state 為undefined,此時(shí)我們可借機(jī)設(shè)置并返回應(yīng)用的初始 state凯亮。
注意:
不要修改state边臼。使用Object.assign()新建了一個(gè)副本。不能這樣使用Object.assign(state, { visibilityFilter: action.filter })假消,因?yàn)樗鼤?huì)改變第一個(gè)參數(shù)的值柠并。你必須把第一個(gè)參數(shù)設(shè)置為空對(duì)象。你也可以開啟對(duì)ES7提案對(duì)象展開運(yùn)算符的支持, 從而使用{ ...state, ...newState }達(dá)到相同的目的富拗。
在default情況下返回舊的state臼予。遇到未知的 action 時(shí),一定要返回舊的state啃沪。
Object.assign須知
Object.assign()是 ES6 特性粘拾,但多數(shù)瀏覽器并不支持。你要么使用 polyfill创千,Babel 插件缰雇,或者使用其它庫(kù)如_.assign()提供的幫助方法。
switch和樣板代碼須知
switch語(yǔ)句并不是嚴(yán)格意義上的樣板代碼追驴。Flux 中真實(shí)的樣板代碼是概念性的:更新必須要發(fā)送械哟、Store 必須要注冊(cè)到 Dispatcher、Store 必須是對(duì)象(開發(fā)同構(gòu)應(yīng)用時(shí)變得非常復(fù)雜)殿雪。為了解決這些問(wèn)題戒良,Redux 放棄了 event emitters(事件發(fā)送器),轉(zhuǎn)而使用純 reducer冠摄。
很不幸到現(xiàn)在為止糯崎,還有很多人存在一個(gè)誤區(qū):根據(jù)文檔中是否使用switch來(lái)決定是否使用它。如果你不喜歡switch河泳,完全可以自定義一個(gè)createReducer函數(shù)來(lái)接收一個(gè)事件處理函數(shù)列表沃呢,參照"減少樣板代碼"。
注意每個(gè) reducer 只負(fù)責(zé)管理全局 state 中它負(fù)責(zé)的一部分拆挥。每個(gè) reducer 的state參數(shù)都不同薄霜,分別對(duì)應(yīng)它管理的那部分 state 數(shù)據(jù)。
現(xiàn)在看過(guò)起來(lái)好多了纸兔!隨著應(yīng)用的膨脹惰瓜,我們還可以將拆分后的 reducer 放到不同的文件中, 以保持其獨(dú)立性并用于專門處理不同的數(shù)據(jù)域。
Redux 提供了combineReducers()工具類汉矿,combineReducers()所做的只是生成一個(gè)函數(shù)崎坊,這個(gè)函數(shù)來(lái)調(diào)用你的一系列 reducer,每個(gè) reducer根據(jù)它們的 key 來(lái)篩選出 state 中的一部分?jǐn)?shù)據(jù)并處理洲拇,然后這個(gè)生成的函數(shù)再將所有 reducer 的結(jié)果合并成一個(gè)大的對(duì)象奈揍。
Store
在前面的章節(jié)中曲尸,我們學(xué)會(huì)了使用action來(lái)描述“發(fā)生了什么”,和使用reducers來(lái)根據(jù) action 更新 state 的用法男翰。
Store就是把它們聯(lián)系到一起的對(duì)象另患。Store 有以下職責(zé):
維持應(yīng)用的 state;
提供getState()方法獲取 state蛾绎;
提供dispatch(action)方法更新 state昆箕;
通過(guò)subscribe(listener)注冊(cè)監(jiān)聽器;
通過(guò)subscribe(listener)返回的函數(shù)注銷監(jiān)聽器。
再次強(qiáng)調(diào)一下Redux 應(yīng)用只有一個(gè)單一的 store租冠。當(dāng)需要拆分?jǐn)?shù)據(jù)處理邏輯時(shí)为严,你應(yīng)該使用reducer 組合而不是創(chuàng)建多個(gè) store。
根據(jù)已有的 reducer 來(lái)創(chuàng)建 store 是非常容易的肺稀。在前一個(gè)章節(jié)中第股,我們使用combineReducers()將多個(gè) reducer 合并成為一個(gè)。現(xiàn)在我們將其導(dǎo)入话原,并傳遞createStore()夕吻。
createStore()的第二個(gè)參數(shù)是可選的, 用于設(shè)置 state 初始狀態(tài)。這對(duì)開發(fā)同構(gòu)應(yīng)用時(shí)非常有用繁仁,服務(wù)器端 redux 應(yīng)用的 state 結(jié)構(gòu)可以與客戶端保持一致, 那么客戶端可以將從網(wǎng)絡(luò)接收到的服務(wù)端 state 直接用于本地?cái)?shù)據(jù)初始化涉馅。
7.Webpack使用
什么是Webpack?
事實(shí)上它是一個(gè)打包工具黄虱,而不是像RequireJS或SeaJS這樣的模塊加載器稚矿,通過(guò)使用Webpack,能夠像Node.js一樣處理依賴關(guān)系捻浦,然后解析出模塊之間的依賴晤揣,將代碼打包
https://fakefish.github.io/react-webpack-cookbook/Getting-started.html
https://segmentfault.com/a/1190000002767365
參考資料:
ReactJS官網(wǎng)地址:http://facebook.github.io/react/
Github地址:https://github.com/facebook/react
http://www.ruanyifeng.com/blog/2015/03/react.html
https://segmentfault.com/a/1190000002767365
https://fakefish.github.io/react-webpack-cookbook/Getting-started.html