##有限狀態(tài)自動(dòng)機(jī),簡(jiǎn)稱狀態(tài)機(jī),是表示有限個(gè)狀態(tài)以及在這些狀態(tài)之間的轉(zhuǎn)移和動(dòng)作等行為的數(shù)學(xué)模型棺禾。
React和React Native的狀態(tài)
##有限狀態(tài)機(jī)(Finite-state machine)是一個(gè)非常有用的模型腹备,可以模擬世界上大部分事物垫桂。
簡(jiǎn)單說霞溪,它有三個(gè)典型特征:
1:事物包含的狀態(tài)總數(shù)(state)是有限的。
2:任一時(shí)刻沾歪,事物僅且只能處于一種狀態(tài)之中漂彤。
3:某種事件驅(qū)動(dòng)下,可以導(dǎo)致事物從一種狀態(tài)切換到另一種狀態(tài)灾搏。
在維基百科中稱:有限狀態(tài)機(jī)FSM是設(shè)計(jì)和實(shí)現(xiàn)事件驅(qū)動(dòng)程序內(nèi)復(fù)雜行為組織原則的有力工具挫望。
傳統(tǒng)的MVC設(shè)計(jì)中
它對(duì)JavaScript的意義在于,很多對(duì)象可以寫成有限狀態(tài)機(jī)狂窑。
有限狀態(tài)機(jī)的寫法媳板,邏輯清晰,表達(dá)力強(qiáng)泉哈,有利于封裝事件拷肌。一個(gè)對(duì)象的狀態(tài)越多到旦、發(fā)生的事件越多,就越適合采用有限狀態(tài)機(jī)的寫法巨缘。
另外,JavaScript語言是一種異步操作特別多的語言采呐,常用的解決方法是指定回調(diào)函數(shù)若锁,但這樣會(huì)造成代碼結(jié)構(gòu)混亂、難以測(cè)試和除錯(cuò)等問題斧吐。有限狀態(tài)機(jī)提供了更好的辦法:把異步操作與對(duì)象的狀態(tài)改變掛鉤又固,當(dāng)異步操作結(jié)束的時(shí)候,發(fā)生相應(yīng)的狀態(tài)改變煤率,由此再觸發(fā)其他操作仰冠。這要比回調(diào)函數(shù)、事件監(jiān)聽蝶糯、發(fā)布/訂閱等解決方案洋只,在邏輯上更合理,更易于降低代碼的復(fù)雜度昼捍。
有限狀態(tài)機(jī)非常重要的一點(diǎn)就是講用戶的操作行為,也就是組件的事件響應(yīng)與組件的表現(xiàn)分離開來.通過建立一個(gè)有限狀態(tài)機(jī)的組件時(shí),我們完全不關(guān)心用戶的操作行為具體做了什么,這時(shí)組件可能會(huì)有幾種狀態(tài)對(duì)應(yīng)不同的表現(xiàn)形式,而用戶觸發(fā)的事件僅僅是切換了模型的狀態(tài).至于每個(gè)狀態(tài)的具體表現(xiàn)和行為,我們完全可以單獨(dú)定義,也就說這時(shí)一種行為和響應(yīng)上的解耦.
當(dāng)用戶的操作發(fā)生變化的時(shí)候,我們僅僅需要改變根數(shù)據(jù),也就是state源.而不需要像以往的MVC設(shè)計(jì)中,當(dāng)行為發(fā)生時(shí),我們既需要在C層改變Model,同時(shí)還要操作View進(jìn)行更新.在復(fù)雜的交互場(chǎng)景中代碼尤其臃腫難以維護(hù).狀態(tài)機(jī)的設(shè)計(jì)思路,很好的解決了這個(gè)問題,用戶操作行為僅僅與修改數(shù)據(jù)關(guān)聯(lián),而與其他無關(guān).
React框架中將UI簡(jiǎn)單的看作有點(diǎn)狀態(tài)機(jī)的組件集合识虚。將UI看作包含了各種各樣的狀態(tài)的組件,并在各種狀態(tài)間切換妒茬,很容易保持UI的一致性担锤。在React中,你只要改變組件的狀態(tài)乍钻,就會(huì)自動(dòng)重新渲染UI肛循,React會(huì)在最有高效的方式下更新虛擬DOM。
通過調(diào)用setState(data, callback)方法银择,改變狀態(tài)多糠,就會(huì)觸發(fā)React更新UI。大部分情況下欢摄,我們不需要提供callback函數(shù)熬丧。React會(huì)自動(dòng)的幫我們更新UI。
后面在好好看看這個(gè)callback的功能和調(diào)用時(shí)機(jī)怀挠。
使用React組件時(shí),免不了就需要跟props,state這兩個(gè)屬性打交道.
props是從父組件或者組件創(chuàng)建時(shí)外部傳遞來的,大多數(shù)組件在創(chuàng)建時(shí)就可以使用各種參數(shù)來進(jìn)行定制,這些定制的參數(shù)就props,props是在父組件中指定析蝴,而且一經(jīng)指定,在被指定的組件的生命周期中則不再改變
state也是用來控制描述一個(gè)組件的,對(duì)于需要改變的數(shù)據(jù)绿淋,我們需要使用state闷畸。
那么什么樣的組件該有state呢?
大部分的組件應(yīng)該從props屬性中獲取數(shù)據(jù)并渲染。但有的時(shí)候組件得相應(yīng)用戶輸入或者交互響應(yīng)吞滞,或同服務(wù)器交互佑菩,這些情況下會(huì)用到state盾沫。React的官方說法是:盡可能的保持你的組件無狀態(tài)化(個(gè)人的理解就是更好的貼合單向數(shù)據(jù)流這一理念)。為了實(shí)現(xiàn)這個(gè)目標(biāo)殿漠,得保持你的狀態(tài)同業(yè)務(wù)邏輯分離赴精,并減少冗余信息,盡可能保持組件的單一職責(zé)绞幌。
state應(yīng)該包含什么樣的數(shù)據(jù)
UI交互,服務(wù)器交互,會(huì)導(dǎo)致改變的數(shù)據(jù)蕾哟。
state不應(yīng)包含什么樣的數(shù)據(jù)
1.計(jì)算過的數(shù)據(jù)
2.組件
3.從props復(fù)制的數(shù)據(jù)
React官方推薦的一種模式就是:構(gòu)建幾個(gè)無狀態(tài)的組件用來渲染數(shù)據(jù),在這些之上構(gòu)建一個(gè)有狀態(tài)的組件同用戶和服務(wù)交互莲蜘,數(shù)據(jù)通過props傳遞給無狀態(tài)的組件谭确。
React的作者認(rèn)為,組件應(yīng)該同關(guān)注分離票渠,而不是同模板和展現(xiàn)邏輯分離逐哈。結(jié)構(gòu)化標(biāo)記和生成結(jié)構(gòu)化標(biāo)記的代碼是緊密關(guān)聯(lián)的,此外问顷,展現(xiàn)邏輯一般都很復(fù)雜昂秃,使用模板語言會(huì)使展現(xiàn)變得笨重。
React解決這個(gè)問題的方式就是:直接通過JavaScript代碼生成虛擬Dom和組件樹择诈,這樣的話械蹋,你就可以使用JavaScript富豐的表達(dá)力去構(gòu)建UI。為了使這個(gè)過程變得更簡(jiǎn)單羞芍,React創(chuàng)建了類似HTML的語法去構(gòu)建節(jié)點(diǎn)樹哗戈,也就是JSX了。這樣可以更方便的創(chuàng)建模板化的組件,方便代碼復(fù)用.
如果一個(gè)組件的數(shù)據(jù)都是不變的,這意味著UI顯示部分也是不變的,那么它就不應(yīng)當(dāng)成為一個(gè)單獨(dú)的RN組件,因?yàn)閱为?dú)的RN組件肯定是數(shù)據(jù)會(huì)被改變的.
對(duì)于無狀態(tài)的RN組件來說,會(huì)被改變的數(shù)據(jù)來自于它的props(屬性),而對(duì)于有狀態(tài)的RN組件來說,會(huì)被改變的數(shù)據(jù)不僅來自于它的props,還來自于它的state(狀態(tài)機(jī)變量).盡可能的讓自定義的組件成為無狀態(tài)的RN組件,以為者盡可能的讓自定義的RN組件沒有狀態(tài)機(jī)變量.
一個(gè)好的設(shè)計(jì)思路是:
創(chuàng)建多個(gè)只負(fù)責(zé)渲染的無狀態(tài)的RN組件,將他們封裝在一個(gè)有狀態(tài)的RN組件中,并把這個(gè)有狀態(tài)的RN組件的狀態(tài)機(jī)變量的值通過props的形式傳遞給無狀態(tài)的RN組件中.在這種設(shè)計(jì)思路下,有狀態(tài)的RN組件封裝了UI的交互邏輯,而無狀態(tài)的RN組件只負(fù)責(zé)渲染UI界面.
但是狀態(tài)機(jī)變量的改變會(huì)導(dǎo)致RN組件的重新渲染,所以提高RN應(yīng)用程序性能的一種方式就是努力減少狀態(tài)機(jī)變量的數(shù)目.
在RN組件的render函數(shù)中,在正確的位置引用狀態(tài)機(jī)變量.
組件之間的通信:
父組件向子組件傳遞消息,數(shù)據(jù)通過回調(diào)父組件傳遞給自己的回調(diào)函數(shù)來實(shí)現(xiàn).回調(diào)函數(shù)于父組件設(shè)定,被保存在子組件的某個(gè)屬性中,等待需要向父組件傳遞消息的時(shí)候調(diào)用.
除了setState函數(shù)意外,RN還提供了replaceState函數(shù)與forceUpdate函數(shù)
狀態(tài)機(jī)的優(yōu)點(diǎn):
1)有限狀態(tài)機(jī)是定義組件的一種好用的設(shè)計(jì)模式荷科,能夠讓組件的代碼看起來更加清晰唯咬,而且易于理解;
2)有限狀態(tài)機(jī)這種模式適合有明顯狀態(tài)特點(diǎn)的組件畏浆;
3)本文所舉的例子不夠貼近實(shí)際項(xiàng)目胆胰,近期會(huì)看看自己做過的項(xiàng)目中有哪些適合用狀態(tài)機(jī)模式來重寫的模塊,到時(shí)候再寫博客來與大家分享刻获。
有一個(gè)異步操作(light.fadeOut)蜀涨。如果不希望狀態(tài)立即改變,就要讓回調(diào)函數(shù)返回StateMachine.ASYNC蝎毡,表示狀態(tài)暫時(shí)不改變厚柳;等到異步操作結(jié)束,再調(diào)用transition方法沐兵,使得狀態(tài)發(fā)生改變别垮。