基于MVC理解React+Redux

我認為MVC模式雖然已經(jīng)誕生了許多年,也有無數(shù)前端框架遵循了MVC模式,但我們在前端開發(fā)時凿跳,很多時候還是忽略了這個模式蘊含的思想坑傅。該思想的核心就是職責(zé)分離僵驰,這種分離又隱含了“信息專家模式”的意義,直白地說,就是“專業(yè)的事情應(yīng)該交給專業(yè)的人去做”矢渊。

MVC(Model-View-Controller)的三個角色其實是各司其職:

  • model持有UI要展現(xiàn)的數(shù)據(jù)
  • View即UI的展現(xiàn)
  • Controller用于控制

以React來說继准,它就應(yīng)該只專注于View的呈現(xiàn),并將這些展現(xiàn)元素封裝為Component矮男。這些Component要展現(xiàn)的props可以視為Model所持有的數(shù)據(jù)移必。

那么,什么情況下會導(dǎo)致View產(chǎn)生變化呢毡鉴?從表象上看崔泵,似乎引起變化的原因是由于客戶端的某種請求或交互操作產(chǎn)生的事件。實則從業(yè)務(wù)上說猪瞬,其實就是要改變Model的值憎瘸,而UI的交互操作不過是對這種變化的界面展現(xiàn)罷了。換言之陈瘦,View的變化其實應(yīng)該通過Model的變化來傳遞幌甘。

當(dāng)我們需要改變View時,一種做法是直接在View上做文章痊项,通過編寫針對UI元素的控制邏輯去改變View锅风。另一種做法就是遵循MVC模式,應(yīng)該通過Controller去改變Model的結(jié)構(gòu)鞍泉,然后通知View去改變自己(或者理解為View偵聽到Model的變化皱埠,從而改變自己)。

React結(jié)合Redux框架做的正是這樣的事情咖驮。在設(shè)計React Component時边器,我們需要通過UI的Layout來規(guī)劃我們的Component,包括Component的分解與組合托修。呈現(xiàn)Component的過程就可以抽象為一個函數(shù)忘巧,這個函數(shù)接收一個輸入對象model,返回一個包裹了HTML元素與Model的DOM`結(jié)構(gòu)诀黍。如以下偽代碼:

const render = (model) => DOM

如果業(yè)務(wù)邏輯要求操作View的DOM袋坑,其實就是對DOM包裹的Model進行操作,例如添加或修改某個<li>眯勾,其本質(zhì)是要添加或修改<li>元素中的值枣宫,這個值來自于Model。在Redux中吃环,其實就是發(fā)起一個action也颤。

執(zhí)行action的目的雖然是修改Model,不過在Redux中郁轻,我們盡量希望遵循FP的思想設(shè)計出所謂的“純函數(shù)”翅娶,于是Redux就引入了reducer函數(shù)文留,這個函數(shù)要做的事情其實就是對Model進行transform(可以考慮引入immutable.js來存儲和操作Modle)。一旦Model對象發(fā)生了變化(并不是真正發(fā)生了變化竭沫,而是產(chǎn)生了一個新的Model)燥翅,Redux就會通知React Component根據(jù)新獲得的Model去重新Render。

顯然蜕提,React扮演的是View的角色森书,Redux則是Controller,至于Model就是Redux Store中存儲的State谎势。我們要從MVC模式的角度去思考React+Redux開發(fā)凛膏,把代碼需要做的每件事情想清楚,明確是誰的職責(zé)脏榆,如此才不至于在實現(xiàn)時走歪路猖毫,不討好地去編寫大量View的控制邏輯,尤其是那些牽涉到parent-child組件的遞歸關(guān)系時须喂,可能會讓前端代碼燉成一鍋粥吁断。

舉個實例。

我們要在前端編寫一個過濾器镊折,UI展現(xiàn)與控制邏輯類似Logiform胯府,如下圖所示:

Logiform的過濾器

這個過濾器可以理解為以Condition為根的一個遞歸嵌套樹形結(jié)構(gòu)介衔,枝為Group恨胚,而葉為ExpressionGroup還可以嵌套Group或者Expression炎咖≡吲荩可以添加、刪除GroupExpression乘盼,也可以調(diào)整它們在樹中所處的位置升熊。

針對這樣的需求,如果我們企圖在React Component中直接去操控和管理這些邏輯绸栅,就需要考慮Component的父子關(guān)系级野,還需要考慮添加或刪除Dom節(jié)點對整棵樹的影響。

如果我們站在前述MVC模式的角度來考慮過濾器樹的呈現(xiàn)與界面控制粹胯,其實不過就是針對Condition對象模型的操作罷了蓖柔。這個時候,我們可以不用去操心DOM節(jié)點之間的關(guān)系风纠,而是直接用React Component去render模型對象况鸣。對象的粗略結(jié)構(gòu)如下所示:

{ 
  "id": 1, 
  "operator": "and", 
  "conditions": [
    {
      "id": 2,
      "type": "expression",
      "operator": "=",
      "fieldId": "11000",
      "value": 3
    },
    {
      "id": 3,
      "type": "group",
      "operator": "or",
      "conditions": [
        {
          "id": 4,
          "type": "expression",
          "operator": "<=",
          "fieldId": "11001",
          "value": 20
        }
    ]
  }]
}

由于render是一種只讀的操作,要在React Component中去render這樣的結(jié)構(gòu)是非常容易的竹观。如上镐捧,當(dāng)我們要刪除id為2的Expression時潜索,其實就是去編寫一個reducer,將其轉(zhuǎn)換為如下的對象:

{ 
  "id": 1, 
  "operator": "and", 
  "conditions": [
    {
      "id": 3,
      "type": "group",
      "operator": "or",
      "conditions": [
        {
          "id": 4,
          "type": "expression",
          "operator": "<=",
          "fieldId": "11001",
          "value": 20
        }
    ]
  }]
}

render對UI的呈現(xiàn)與控制邏輯完全相同懂酱,并不需要再去控制復(fù)雜的DOM竹习。

概況下來,React+Redux的主體流程為:

  • 通過action獲得model列牺,并將其作為state存儲到Store中由驹;
  • 傳遞給React Component,按照某種設(shè)計呈現(xiàn)model數(shù)據(jù)昔园;
  • 調(diào)用action發(fā)起update請求蔓榄,從而調(diào)用reducer生成新的state存儲到Store中;
  • redux通知React Component重新Render默刚。

這是MVC三種角色各司其職相互協(xié)作的結(jié)果甥郑。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市荤西,隨后出現(xiàn)的幾起案子澜搅,更是在濱河造成了極大的恐慌,老刑警劉巖邪锌,帶你破解...
    沈念sama閱讀 217,657評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件勉躺,死亡現(xiàn)場離奇詭異,居然都是意外死亡觅丰,警方通過查閱死者的電腦和手機饵溅,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,889評論 3 394
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來妇萄,“玉大人蜕企,你說我怎么就攤上這事」诰洌” “怎么了轻掩?”我有些...
    開封第一講書人閱讀 164,057評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長懦底。 經(jīng)常有香客問我唇牧,道長,這世上最難降的妖魔是什么聚唐? 我笑而不...
    開封第一講書人閱讀 58,509評論 1 293
  • 正文 為了忘掉前任丐重,我火速辦了婚禮,結(jié)果婚禮上拱层,老公的妹妹穿的比我還像新娘弥臼。我一直安慰自己,他們只是感情好根灯,可當(dāng)我...
    茶點故事閱讀 67,562評論 6 392
  • 文/花漫 我一把揭開白布径缅。 她就那樣靜靜地躺著掺栅,像睡著了一般。 火紅的嫁衣襯著肌膚如雪纳猪。 梳的紋絲不亂的頭發(fā)上氧卧,一...
    開封第一講書人閱讀 51,443評論 1 302
  • 那天,我揣著相機與錄音氏堤,去河邊找鬼沙绝。 笑死,一個胖子當(dāng)著我的面吹牛鼠锈,可吹牛的內(nèi)容都是我干的闪檬。 我是一名探鬼主播,決...
    沈念sama閱讀 40,251評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼购笆,長吁一口氣:“原來是場噩夢啊……” “哼粗悯!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起同欠,我...
    開封第一講書人閱讀 39,129評論 0 276
  • 序言:老撾萬榮一對情侶失蹤样傍,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后铺遂,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體衫哥,經(jīng)...
    沈念sama閱讀 45,561評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,779評論 3 335
  • 正文 我和宋清朗相戀三年襟锐,在試婚紗的時候發(fā)現(xiàn)自己被綠了撤逢。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,902評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡捌斧,死狀恐怖笛质,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情捞蚂,我是刑警寧澤,帶...
    沈念sama閱讀 35,621評論 5 345
  • 正文 年R本政府宣布跷究,位于F島的核電站姓迅,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏俊马。R本人自食惡果不足惜丁存,卻給世界環(huán)境...
    茶點故事閱讀 41,220評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望柴我。 院中可真熱鬧解寝,春花似錦、人聲如沸艘儒。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,838評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至觉增,卻和暖如春兵拢,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背逾礁。 一陣腳步聲響...
    開封第一講書人閱讀 32,971評論 1 269
  • 我被黑心中介騙來泰國打工说铃, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人嘹履。 一個月前我還...
    沈念sama閱讀 48,025評論 2 370
  • 正文 我出身青樓腻扇,卻偏偏與公主長得像,于是被迫代替她去往敵國和親砾嫉。 傳聞我的和親對象是個殘疾皇子衙解,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,843評論 2 354

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

  • React+Redux 這種開發(fā)模式在公司跌跌撞撞的使用已經(jīng)有五個月了。對這種開發(fā)模式進行一個MVC的總結(jié)算也是跟...
    FanChengSheng閱讀 6,299評論 1 13
  • 原教程內(nèi)容詳見精益 React 學(xué)習(xí)指南焰枢,這只是我在學(xué)習(xí)過程中的一些閱讀筆記蚓峦,個人覺得該教程講解深入淺出,比目前大...
    leonaxiong閱讀 2,834評論 1 18
  • React+Redux非常精煉,良好運用將發(fā)揮出極強勁的生產(chǎn)力荐绝。但最大的挑戰(zhàn)來自于函數(shù)式編程(FP)范式一汽。在工程化...
    小馬哥歸來閱讀 154,422評論 21 166
  • 做React需要會什么召夹? react的功能其實很單一,主要負責(zé)渲染的功能恕沫,現(xiàn)有的框架监憎,比如angular是一個大而...
    蒼都閱讀 14,759評論 1 139
  • 今天看吳軍老師的文章,成功并不難婶溯,在于少犯錯誤鲸阔。對我啟發(fā)很大。 在賭博的過程中迄委,其實也就是你贏我一次褐筛,我贏你一次的...
    linhuizhang閱讀 488評論 0 1