JavaScript狀態(tài)機(jī)的理解

##有限狀態(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ā)生改變别垮。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市扎谎,隨后出現(xiàn)的幾起案子碳想,更是在濱河造成了極大的恐慌烧董,老刑警劉巖,帶你破解...
    沈念sama閱讀 223,207評(píng)論 6 521
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件胧奔,死亡現(xiàn)場(chǎng)離奇詭異逊移,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)葡盗,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,455評(píng)論 3 400
  • 文/潘曉璐 我一進(jìn)店門螟左,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人觅够,你說我怎么就攤上這事∠锵” “怎么了喘先?”我有些...
    開封第一講書人閱讀 170,031評(píng)論 0 366
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)廷粒。 經(jīng)常有香客問我窘拯,道長(zhǎng),這世上最難降的妖魔是什么坝茎? 我笑而不...
    開封第一講書人閱讀 60,334評(píng)論 1 300
  • 正文 為了忘掉前任涤姊,我火速辦了婚禮,結(jié)果婚禮上嗤放,老公的妹妹穿的比我還像新娘思喊。我一直安慰自己,他們只是感情好次酌,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,322評(píng)論 6 398
  • 文/花漫 我一把揭開白布恨课。 她就那樣靜靜地躺著,像睡著了一般岳服。 火紅的嫁衣襯著肌膚如雪剂公。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,895評(píng)論 1 314
  • 那天吊宋,我揣著相機(jī)與錄音纲辽,去河邊找鬼。 笑死璃搜,一個(gè)胖子當(dāng)著我的面吹牛拖吼,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播腺劣,決...
    沈念sama閱讀 41,300評(píng)論 3 424
  • 文/蒼蘭香墨 我猛地睜開眼绿贞,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了橘原?” 一聲冷哼從身側(cè)響起籍铁,我...
    開封第一講書人閱讀 40,264評(píng)論 0 277
  • 序言:老撾萬榮一對(duì)情侶失蹤涡上,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后拒名,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體吩愧,經(jīng)...
    沈念sama閱讀 46,784評(píng)論 1 321
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,870評(píng)論 3 343
  • 正文 我和宋清朗相戀三年增显,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了雁佳。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,989評(píng)論 1 354
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡同云,死狀恐怖糖权,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情炸站,我是刑警寧澤味赃,帶...
    沈念sama閱讀 36,649評(píng)論 5 351
  • 正文 年R本政府宣布稠腊,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏疟位。R本人自食惡果不足惜砂代,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,331評(píng)論 3 336
  • 文/蒙蒙 一厅克、第九天 我趴在偏房一處隱蔽的房頂上張望翎朱。 院中可真熱鬧,春花似錦忌堂、人聲如沸盒至。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,814評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽妄迁。三九已至,卻和暖如春李命,著一層夾襖步出監(jiān)牢的瞬間登淘,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,940評(píng)論 1 275
  • 我被黑心中介騙來泰國(guó)打工封字, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留黔州,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,452評(píng)論 3 379
  • 正文 我出身青樓阔籽,卻偏偏與公主長(zhǎng)得像流妻,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子笆制,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,995評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容