##有限狀態自動機,簡稱狀態機,是表示有限個狀態以及在這些狀態之間的轉移和動作等行為的數學模型。
React和React Native的狀態
##有限狀態機(Finite-state machine)是一個非常有用的模型,可以模擬世界上大部分事物。
簡單說,它有三個典型特征:
1:事物包含的狀態總數(state)是有限的。
2:任一時刻,事物僅且只能處于一種狀態之中。
3:某種事件驅動下,可以導致事物從一種狀態切換到另一種狀態。
在維基百科中稱:有限狀態機FSM是設計和實現事件驅動程序內復雜行為組織原則的有力工具。
傳統的MVC設計中
它對JavaScript的意義在于,很多對象可以寫成有限狀態機。
有限狀態機的寫法,邏輯清晰,表達力強,有利于封裝事件。一個對象的狀態越多、發生的事件越多,就越適合采用有限狀態機的寫法。
另外,JavaScript語言是一種異步操作特別多的語言,常用的解決方法是指定回調函數,但這樣會造成代碼結構混亂、難以測試和除錯等問題。有限狀態機提供了更好的辦法:把異步操作與對象的狀態改變掛鉤,當異步操作結束的時候,發生相應的狀態改變,由此再觸發其他操作。這要比回調函數、事件監聽、發布/訂閱等解決方案,在邏輯上更合理,更易于降低代碼的復雜度。
有限狀態機非常重要的一點就是講用戶的操作行為,也就是組件的事件響應與組件的表現分離開來.通過建立一個有限狀態機的組件時,我們完全不關心用戶的操作行為具體做了什么,這時組件可能會有幾種狀態對應不同的表現形式,而用戶觸發的事件僅僅是切換了模型的狀態.至于每個狀態的具體表現和行為,我們完全可以單獨定義,也就說這時一種行為和響應上的解耦.
當用戶的操作發生變化的時候,我們僅僅需要改變根數據,也就是state源.而不需要像以往的MVC設計中,當行為發生時,我們既需要在C層改變Model,同時還要操作View進行更新.在復雜的交互場景中代碼尤其臃腫難以維護.狀態機的設計思路,很好的解決了這個問題,用戶操作行為僅僅與修改數據關聯,而與其他無關.
React框架中將UI簡單的看作有點狀態機的組件集合。將UI看作包含了各種各樣的狀態的組件,并在各種狀態間切換,很容易保持UI的一致性。在React中,你只要改變組件的狀態,就會自動重新渲染UI,React會在最有高效的方式下更新虛擬DOM。
通過調用setState(data, callback)方法,改變狀態,就會觸發React更新UI。大部分情況下,我們不需要提供callback函數。React會自動的幫我們更新UI。
后面在好好看看這個callback的功能和調用時機。
使用React組件時,免不了就需要跟props,state這兩個屬性打交道.
props是從父組件或者組件創建時外部傳遞來的,大多數組件在創建時就可以使用各種參數來進行定制,這些定制的參數就props,props是在父組件中指定,而且一經指定,在被指定的組件的生命周期中則不再改變
state也是用來控制描述一個組件的,對于需要改變的數據,我們需要使用state。
那么什么樣的組件該有state呢?
大部分的組件應該從props屬性中獲取數據并渲染。但有的時候組件得相應用戶輸入或者交互響應,或同服務器交互,這些情況下會用到state。React的官方說法是:盡可能的保持你的組件無狀態化(個人的理解就是更好的貼合單向數據流這一理念)。為了實現這個目標,得保持你的狀態同業務邏輯分離,并減少冗余信息,盡可能保持組件的單一職責。
state應該包含什么樣的數據
UI交互,服務器交互,會導致改變的數據。
state不應包含什么樣的數據
1.計算過的數據
2.組件
3.從props復制的數據
React官方推薦的一種模式就是:構建幾個無狀態的組件用來渲染數據,在這些之上構建一個有狀態的組件同用戶和服務交互,數據通過props傳遞給無狀態的組件。
React的作者認為,組件應該同關注分離,而不是同模板和展現邏輯分離。結構化標記和生成結構化標記的代碼是緊密關聯的,此外,展現邏輯一般都很復雜,使用模板語言會使展現變得笨重。
React解決這個問題的方式就是:直接通過JavaScript代碼生成虛擬Dom和組件樹,這樣的話,你就可以使用JavaScript富豐的表達力去構建UI。為了使這個過程變得更簡單,React創建了類似HTML的語法去構建節點樹,也就是JSX了。這樣可以更方便的創建模板化的組件,方便代碼復用.
如果一個組件的數據都是不變的,這意味著UI顯示部分也是不變的,那么它就不應當成為一個單獨的RN組件,因為單獨的RN組件肯定是數據會被改變的.
對于無狀態的RN組件來說,會被改變的數據來自于它的props(屬性),而對于有狀態的RN組件來說,會被改變的數據不僅來自于它的props,還來自于它的state(狀態機變量).盡可能的讓自定義的組件成為無狀態的RN組件,以為者盡可能的讓自定義的RN組件沒有狀態機變量.
一個好的設計思路是:
創建多個只負責渲染的無狀態的RN組件,將他們封裝在一個有狀態的RN組件中,并把這個有狀態的RN組件的狀態機變量的值通過props的形式傳遞給無狀態的RN組件中.在這種設計思路下,有狀態的RN組件封裝了UI的交互邏輯,而無狀態的RN組件只負責渲染UI界面.
但是狀態機變量的改變會導致RN組件的重新渲染,所以提高RN應用程序性能的一種方式就是努力減少狀態機變量的數目.
在RN組件的render函數中,在正確的位置引用狀態機變量.
組件之間的通信:
父組件向子組件傳遞消息,數據通過回調父組件傳遞給自己的回調函數來實現.回調函數于父組件設定,被保存在子組件的某個屬性中,等待需要向父組件傳遞消息的時候調用.
除了setState函數意外,RN還提供了replaceState函數與forceUpdate函數
狀態機的優點:
1)有限狀態機是定義組件的一種好用的設計模式,能夠讓組件的代碼看起來更加清晰,而且易于理解;
2)有限狀態機這種模式適合有明顯狀態特點的組件;
3)本文所舉的例子不夠貼近實際項目,近期會看看自己做過的項目中有哪些適合用狀態機模式來重寫的模塊,到時候再寫博客來與大家分享。
有一個異步操作(light.fadeOut)。如果不希望狀態立即改變,就要讓回調函數返回StateMachine.ASYNC,表示狀態暫時不改變;等到異步操作結束,再調用transition方法,使得狀態發生改變。