<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

       

      引言:為什么數據流管理如此重要?react的核心思想就是:UI=render(data)data就是我們說的數據流,renderreact提供的純函數,所以用戶界面的展示完全取決于數據層。這篇文章希望能用最淺顯易懂的話,將react中的數據流管理,從自身到借助第三方庫,將這些概念理清楚。我會列舉幾個當下最熱的庫,包括它們的思想以及優缺點,適用于哪些業務場景。這篇文章不是教程,不會講如何去使用它們,更不會一言不合就搬源碼,正如文章標題所說,只是淺談,希望讀者在讀完以后就算原先沒有使用過這些庫,也能大致有個思路,知道該如何選擇性地深入學習。

       

      在本文正式開始之前,我先試圖講清楚兩個概念,狀態和數據:

      我們都知道,react是利用可復用的組件來構建界面的,組件本質上是一個有限狀態機,它能夠記住當前所處的狀態,并且能夠根據不同的狀態變化做出不同的操作。在react中,把這種狀態定義為state,用來描述該組件對應的當前交互界面,表示當前界面展示的一種狀況,react正是通過管理狀態來實現對組件的管理,當state發生變更時,react會自動去執行相應的操作:繪制界面。

      所以狀態是針對react component這種有限狀態機才出現的名詞,而數據就廣泛了,它不光是指server層返回給前端的數據,react中的狀態也是一種數據,當我們改變數據的同時,就要通過改變狀態去引發界面的變更;我們真正要關心的是數據層的管理,我們今天所討論的數據流管理方案,特別是后面介紹的幾種第三方庫,不光是配合react,也可以配合其他的View框架(VueAngular等等),就好比開頭提到的那個公式,引申一下:UI = X(data),但今天主要是圍繞react來講的,因此我們在說react的狀態管理其實和數據流管理是一樣的,包括我們會借助第三方庫來幫助react管理狀態,希望不要有小伙伴太糾結于此。

       

      一,react自身的數據流管理方案

      我們先來回顧一下,react自身是如何管理數據流的(也可以理解為如何管理應用狀態):

       

      react是自上而下的單向組件數據流,容器組件&展示組件(也叫傻瓜組件&聰明組件)是最常用的react組件設計方案,容器組件負責處理復雜的業務邏輯以及數據,展示組件負責處理UI層,通常我們會將展示組件抽出來進行復用或者組件庫的封裝,容器組件自身通過state來管理狀態,setState更新狀態,從而更新UI,通過props將自身的state傳遞給展示組件實現通信。

       

      這是當業務需求不復雜,頁面較簡單時我們常用的數據流處理方式,僅用react自身提供的propsstate來管理足矣,但是如果稍微增加一點復雜度呢,比如當我們項目中遇到這些問題:

       

      1,如何實現跨組件通信、狀態同步以及狀態共享?

      react V16.3以前,通過狀態提升至最近的共同父組件來實現。(雖然有官方提供的context API,但是舊版本存在一個問題:看似跨組件,實則還是逐級傳遞,如果中間組件使用了ShouldComponentUpdate檢測到當前stateprops沒有變化,return false,那么context就會無法透傳,因此context沒有被官方推薦使用)。

       

      react V16.3版本以后,新版本context解決了之前的問題,可以輕松實現,但依然存在一個問題,context也是將底部子組件的狀態控制交給到了頂級組件,但是頂級組件狀態更新的時候一定會觸發所有子組件的re-render,那么也會帶來損耗。(雖然我們可以通過一些手段來減少重繪,比如在中間組件的SCU里進行一些判斷,但是當項目較大時,我們需要花太多的精力去做這件事)

       

       

      2,如何避免組件臃腫?

      當某個組件的業務邏輯非常復雜時,我們會發現代碼越寫越多,因為我們只能在組件內部去控制數據流,沒辦法抽離,ModelView都放在了View層,整個組件顯得臃腫不堪,業務邏輯統統堆在一塊,難以維護。

       

      3,如何讓狀態變得可預知,甚至可回溯?

      當數據流混亂時,我們一個執行動作可能會觸發一系列的setState,我們如何能夠讓整個數據流變得可監控,甚至可以更細致地去控制每一步數據或狀態的變更?

       

      4,如何處理異步數據流?

      react自身并未提供多種處理異步數據流管理的方案,僅用一個setState已經很難滿足一些復雜的異步流場景;

       

      如何改進?

      這個時候,我們可能需要一個真正的數據流管理工具來幫助react了,我們希望它是真正脫離react組件的概念的,從UI層完全抽離出來,只負責管理數據,讓react只專注于View層的繪制,那這也是為什么我們需要使用那些第三方數據流管理工具的原因,接下來我們就來了解一些當前社區比較熱門的數據流管理工具。

       

      二,redux

      我直接跳過了flux來說redux,主要是因為redux是由flux演變而來,可以說是flux的升級加強版,flux具備的優勢redux也做到了。

       

      redux提供了哪些?

       

      1store:提供了一個全局的store變量,用來存儲我們希望從組件內部抽離出去的那些公用的狀態;

      2action:提供了一個普通對象,用來記錄我們每一次的狀態變更,可日志打印與調試回溯,并且這是唯一的途徑;

      3reducer:提供了一個純函數,用來計算狀態的變更;

       

      為什么需要redux

      很多人在用了一段時間的redux之后,最大的感想就是,redux要寫大量的模板代碼,很麻煩,還不如只用react來管理。特別是在react的新context推出以后,許多人更是直接棄用了redux,甚至覺得redux已死。如果說舊版的context的弊端,我們通過redux配合react-redux來實現跨組件的狀態通信同步等問題,那確實新版本的context可以替換掉這個功能點,但如果你的項目中僅僅是用redux做這些,那思考一下,你是否真的需要redux?也許從一開始你就不需要它。(雖然新版的context功能強大,但是依然是通過一個新的容器組件來替我們管理狀態,那么通過組件管理狀態的問題依舊會存在,Consumer是和Provider一一對應的,在項目復雜度較高時,可能會出現多個Provider,更多個Consumer,甚至會一個Consumer需要對應多個Provider的傳值等一系列復雜的情況,所以我們依然要謹慎使用)

       

      redux的核心競爭力

      1,狀態持久化:global store可以保證組件就算銷毀了也依然保留之前狀態;

      2,狀態可回溯:每個action都會被序列化,Reducer不會修改原有狀態,總是返回新狀態,方便做狀態回溯;

      3Functional Programming:使用純函數,輸出完全依賴輸入,沒有任何副作用;

      4,中間件:針對異步數據流,提供了類express中間件的模式,社區也出現了一大批優秀的第三方插件,能夠更精細地控制數據的流動,對復雜的業務場景起到了緩沖地作用;

       

       

      與其說是redux來幫助react管理狀態,不如說是將react的部分狀態移交至redux那里,redux徹頭徹尾的純函數理念就表明了它不會參與任何狀態變化,完全是由react自己來完成,只不過redux會提供一套工具,react照著說明書來操作罷了,所以這注定了想要接受redux,就必須按照它的規矩來做,除非你不愿意接受這種FP的模式。這種模式有利有弊,有利就是在一個大型的多人團隊中,這種開發模式反而容易形成一種規約,讓整個狀態流程變得清晰,弊端就是對于小規模團隊,尤其是著急發布上線的,這種繁重的代碼模板無疑是一種負擔。

       

      redux的缺點:

      1,繁重的代碼模板:修改一個state可能要動四五個文件,可謂牽一發而動全身;

      2store里狀態殘留:多組件共用store里某個狀態時要注意初始化清空問題;

      3,無腦的發布訂閱:每次dispatch一個action都會遍歷所有的reducer,重新計算connect,這無疑是一種損耗;

      4,交互頻繁時會有卡頓:如果store較大時,且頻繁地修改store,會明顯看到頁面卡頓;

      5,不支持typescript

       

      關于如何優化,網上有很多優秀的案例,redux官方也提供了很多方法,這里不再贅述。redux未來不會有太大的變化,那些弊端還是會繼續保留,但是這依然不會妨礙忠愛它的用戶去使用它。

       

      如果說redux那種強硬的函數式編程模式讓很多人難以接受,那么當他們開始mobx的使用的時候,無疑是一種解脫。

       

      三,mobx

      最開始接觸mobx也是因為redux作者Dan Abramov的那句:Unhappy with reduxtry mobx,我相信很多人也是因為這句話而開始了解學習并使用它的。

       

      下面列舉一些mobx的優勢(和redux進行一個對比)

      1redux不允許直接修改state,而mobx可隨意修改;

      2redux修改狀態必須走一套指定的流程較麻煩,而mobx可以在任何地方直接修改(非嚴格模式下);

      3redux模板代碼文件多,而mobx非常簡潔,就一個文件;

      4redux只有一個storestate or store難以取舍,而mobxstore,你可以把所有的state都放入store中,完全交給mobx來管理,減少顧慮;

      5redux需要對監聽的組件做SCU優化,減少重復render;而mobx都是Smart Component,不用我們手動做SCU

       

      mobx的設計思想:

       

      說了這么多,如果你是第一次了解mobx,是不是聽著就感覺很爽!沒錯,這就是mobx的魅力,那它是如何實現這些功能的呢?這里以mobx 5版本為例,實際上它是利用了ES6proxy來追蹤屬性(舊版本是用Object.defineProperty來實現的)通過隱式訂閱,自動追蹤被監聽的對象變化,然后觸發組件的UI更新;如果說redux是把要做的事情都交給了用戶,來保證自己的純凈,那么mobx就是把最簡易的操作給了用戶,其它的交給mobx內部去實現,用戶不必關心這個過程,ModelView完全分離,我們完全可以將業務邏輯寫在action里,用戶只需要操作Observable data就行了,Observer view會自動做出響應,這就是mobx主打的響應式設計,但是編程風格依然是傳統的面向對象的OO范式。(熟悉Vue的朋友一定對這種響應式設計不陌生,Vue就是利用了數據劫持來實現雙向綁定,其實React + Mobx就是一個復雜點的VueVue 3版本一個重大改變也是將代理交給了proxy

       

      剛剛mobx的優勢說得比較多了,這邊再總結一下:

      1,代碼量少;

      2,基于數據劫持來實現精準定位(真正意義上的局部更新);

      3,多store抽離業務邏輯(Model View分離);

      4,響應式性能良好(頻繁的交互依然可以勝任);

      5,完全可以替代react自身的狀態管理;

      6,支持typescript

       

      但是mobx真的這么完美嗎,當然也有缺陷:

      1,沒有狀態回溯能力:mobx是直接修改對象引用,所以很難去做狀態回溯;(這點redux的優勢就瞬間體現出來了)

      2,沒有中間件:和redux一樣,mobx也沒有很好地辦法處理異步數據流,沒辦法更精細地去控制數據流動;(redux雖然自己不做,但是它提供了applyMiddleware!)

      3store太多:隨著store數的增多,維護成本也會增加,而且多store之間的數據共享以及相互引用也會容易出錯

      4,副作用:mobx直接修改數據,和函數式編程模式強調的純函數相反,這也導致了數據的很多未知性

       

      其實現在主流的數據流管理分為兩大派,一類是以redux為首的函數式庫,還有一類是以mobx為首的響應式庫,其實通過剛剛的介紹,我們會發現,reduxmobx有一個共同的短板,那就是在處理異步數據流的時候,沒有一個很好的解決方案,至少僅僅依靠自身比較吃力,那么接下來給大家介紹一個處理異步數據流的高手:rxjs

       

      四,rxjs

      我相信很多人聽說過rxjs學習曲線異常陡峭,是的,除了眼花繚亂的各類操作符(目前rxjs V6版本有120+個),關鍵是它要求我們在處理事務的時候要貫徹一切皆為流的理念,更是讓初學者難以理解。這一小節并不能讓讀者達到能夠上手使用的程度,正如文章開頭所說,希望讀者(新手)能對rxjs有一個新的認知,知道它是做什么的,它是如何實現的,它有哪些優勢,我們如何選擇它,如果感興趣還需要私下花大量時間去學習掌握各種操作符,但我也會嘗試盡可能地相對于前兩個說得更細致一些。

       

      在開始介紹rxjs之前,我們先來簡單地聊聊什么是響應式編程?我以一個很簡單的小例子來看:a + b = c;如果站在傳統的命令式編程的角度來看這段公式:c的值完全依賴于ab,這時候我們去改變a的值,那我們就需要再去手動計算a + b的值,abc是相互依賴的;那么如果站在響應式編程的角度來看,這個公式又會變成這樣:

      c := a + bab完全不關心c的值,c也完全不關心等式那邊是a或者b,或者還有什么def。。。等式右邊改變值了,左邊會自動更改數值,這就是響應式編程的思維方式。我們再來看前端的框架歷史,傳統命令式編程的代表:jQuery,在過去我們是如何繪制一個頁面的?我們會用jQuery提供的一套API,然后手動操作Dom來進行繪制,很精準,但是很累,因為完全靠手動操作,且改動時性能損耗較大,開發者的注意力完全在如何去繪制上面了;那我們再來看響應式編程的react,它是如何來實現的?開發者根本不用關心界面如何繪制,只要告訴react我們希望頁面長什么樣子,就可以了,剩下的交給reactreact就會自動幫我們繪制界面,還記得開頭時的那個核心思想嗎:UI = render(data),我們只要操作data就可以了,頁面UI會自動作出響應,而且我們一切的操作都是基于內存之中,不會有較大的性能損耗,這就是react響應式編程的精髓,也是為何它叫作react

       

      回到我們的rxjs上,rxjs是如何做到響應式的呢?多虧了它兩種強大的設計模式:觀察者模式和迭代器模式;簡單地介紹一下:

      1,觀察者模式:

       

      在觀察者模式中,有兩個重要的角色:ObservableObserver,熟悉mobx的同學對這個一定不陌生(所以我建議想要學習rxjs的同學,如果對mobx不熟悉,可以先學習一下mobx,然后再學習rxjs,這樣會更容易理解一些),就是可觀察對象和觀察者,可觀察對象(Observable)也就是事件發布者,負責產生事件,而觀察者(Observer)也就是事件響應者,負責對發布的事件作出響應,但是如何連接一個發布者和響應者呢?通過訂閱的形式,也就是subscribe方法(這也類似于reduxstore.subscribe),而在訂閱之前,他們兩者是毫無關聯的,無論Observable發出多少事件,Observer也不會做出任何響應,同樣,當這種訂閱關系中斷時也不會;

       

      2,迭代器模式:

      在這里要先引出一個新的概念:拉取(pull)和推送(push),rxjs官方這兩種協議有更詳細的解釋,我這里就直接引用一下: 

       

      拉取和推送實際上對于觀察者來說就是一個主動與被動的區別,是主動去獲取還是被動地接收。在rxjs中,作為事件響應者(消費者)的Observer對象也有一個next屬性(回調函數),用來接收從發布者那里過來的數據。(站在開發者的角度,我們一定是希望消息是被動地接收,因為我們倡導的就是通過操作data數據層,讓View層進行一個響應,那么這里data數據層一定是事件發布者,而View層就是事件響應者,每當data數據層發生變化時,都會主動推送一個值給View層,這才符合真正意義上的響應式編程,而rxjs做到了!)

       

      如何配合react

      如果說reduxmobx的出現或多或少是因為react的存在,那么不同的是rxjsreact并沒有什么關聯,關于rxjs的歷史這里不多說,感興趣的可以了解一下Reactive Extensionrxjs只是響應式編程在JavaScript中的應用。那么如何幫助react實現狀態管理呢,我們只需要將組件作為事件響應者,然后在next回調里定義好更新組件狀態的動作setState,當接收到數據推送時,就會自動觸發setState,完成界面更新,這其實有點類似于mobx做的事情。(很多人在react項目中并沒有完全只使用rxjs,而是用了這個redux-observable中間件,利用rxjs的操作符來處理異步action

       

       

      除了響應式編程的魅力,rxjs還有什么優勢呢?

      1,純函數:rxjs中數據流動的過程中,不會改變已經存在的Observable實例,會返回一個新的Observable,沒有任何副作用;

      2,強大的操作符:rxjs又被稱為lodash for async,和lodash一樣,擁有眾多強大的操作符來操作數據流,不光是同步數據,特別是針對各種復雜的異步數據流,甚至可以多種事件流組合搭配,匯總到一起處理;

      3,更獨立:rxjs并不依賴于任何一個框架,它可以任意搭配,因為它的關注點完全就是在于數據流的處理上,而且它更偏底層一些

       

      rxjs有哪些缺點呢?

      1,學習曲線陡峭:光是這一點就已經讓大多數人止步于此;

      2,事件流高度抽象:用rxjs的用戶反饋一般都是兩種極端情況,用得好的都覺得這個太厲害了,用得不好的都覺得感覺有點麻煩,增加了項目復雜度。

       

      最后,總結一下各類的適用場景:

      1,當我們項目中復雜程度較低時,建議只用react就可以了;

      2,當我們項目中跨組件通信、數據流同步等情況較多時,建議搭配react的新context api

      3,當項目復雜度一般時,小規模團隊或開發周期較短時,建議使用mobx

      4,當項目復雜度較高時,團隊規模較大或要求對事件分發處理可監控可回溯時,建議使用redux

      5,當項目復雜度較高,且數據流混雜時,建議使用rxjs

       

      結語:其實回顧全篇,我沒有提到一個關鍵點是,各個庫的性能對比如何。其實它們之間一定是有差異的,但是這點性能差異,相對于react自身組件設計不當而導致的性能損耗來說,是可以忽略的,如果你現在的項目覺得性能較差或者頁面卡頓,建議先從react層面去考慮如何進行優化,然后再去考慮如何優化數據管理層。關于上面提到的三個數據流管理工具,有利有弊,針對弊端,網上也有一大批優秀的解決方案和改進,感興趣的讀者可自行查閱。

       

      謝謝!

       

      =============

      ps:這篇文章會發布在攜程公眾號上,不是抄襲,我就是作者,先更新到博客園上而已。

       

      posted on 2019-03-07 09:44  言先生  閱讀(4571)  評論(1)    收藏  舉報

      主站蜘蛛池模板: 亚洲曰韩欧美在线看片| 亚洲日韩av在线观看| 晋江市| 亚洲国产成人不卡高清麻豆| 丁香五月婷激情综合第九色| 亚洲第一无码AV无码专区| 色国产视频| 九九热免费精品在线视频| 精品在免费线中文字幕久久| 午夜成人精品福利网站在线观看| 人妻少妇一区二区三区| 国产尤物精品自在拍视频首页| 国产av国片精品一区二区| 人妻少妇精品视频无码综合| 成人亚洲av免费在线| 永久免费无码网站在线观看| 欧洲码亚洲码的区别入口| 自拍偷在线精品自拍偷99| 国产在线啪| 天堂一区二区三区av| 国产成人精品亚洲精品日日| 亚洲老熟女一区二区三区 | 久操线在视频在线观看| 好深好湿好硬顶到了好爽| 亚洲线精品一区二区三八戒| 芳草地社区在线视频| 日本道精品一区二区三区| 国产二区三区不卡免费| 亚洲AV日韩AV高清在线观看| 亚洲欧美人成电影在线观看| 国产一区二区三区无遮挡| 日本黄页网站免费观看| 久久久久国产精品熟女影院| 国产精品一区二区三区蜜臀 | 辽阳县| 亚洲国产精品高清久久久| 把女人弄爽大黄A大片片| 日本少妇自慰免费完整版| 国产99久久亚洲综合精品西瓜tv| 亚洲成人av日韩在线| 中文字幕av日韩有码|