国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

干貨 | React技術棧耕耘 —— Redux

LdhAndroid / 751人閱讀

摘要:作者小滬江前端開發工程師本文為原創文章,有不當之處歡迎指出。于是,單一數據源規則實施起來,是規定用的頂層容器組件的來存儲單一對象樹,同時交給來管理。顧名思義,當更新時,的回調函數會更新視圖層,以達到訂閱的效果。

作者:小boy (滬江web前端開發工程師)
本文為原創文章,有不當之處歡迎指出。轉載請注明出處。
文章示例代碼:https://github.com/ikcamp/rea...

Redux 是近年來提出的 Flux 思想的一種實踐方案,在它之前也有 reflux 、 fluxxor 等高質量的作品,但短短幾個月就在 GitHub 上獲近萬 star 的成績讓這個后起之秀逐漸成為 Flux 的主流實踐方案。

正如 Redux 官方所稱,React 禁止在視圖層直接操作 DOM 和異步行為 ( removing both asynchrony and direct DOM manipulation ),來拆開異步和變化這一對冤家。但它依然把狀態的管理交到了我們手中。Redux 就是我們的狀態管理小管家。

安利的話先暫時說到這,本期的技術周刊將為你帶來 React-Redux 在滬江前端團隊中的實踐。

0. 放棄

你沒有看錯,在開始之前我們首先談論一下什么情況下不應該用 Redux。
所謂殺雞焉用宰牛刀,任何技術方案都有其適用場景。作為一個思想的實踐方案,Redux 必然會為實現思想立規矩、鋪基礎,放在復雜的 React 應用里,它會是“金科玉律”,而放在結構不算復雜的應用中,它只會是“繁文縟節”。

如果我們將要構建的應用無需多層組件嵌套,狀態變化簡單,數據單一,那么就應放棄 Redux ,選用單純的 React 庫 或其他 MV* 庫。畢竟,沒有人愿意雇傭一個收費比自己收入還高的財務顧問。

1. 思路

首先,我們回顧一下 Redux 的基本思路

當用戶與界面交互時,交互事件的回調函數會觸發 ActionCreators ,它是一個函數,返回一個對象,該對象攜帶了用戶的動作類型和修改 Model 必需的數據,這個對象也被我們稱作 Action 。

以 TodoList 為例,添加一個 Todo 項的 ActionCreator 函數如下所示:

在上例中,addTodo 就是 ActionCreator 函數,該函數返回的對象就是 Action 。

其中 type 為 Redux 中約定的必填屬性,它的作用稍后我們會講到。而 text 則是執行 “添加 Todo 項“ 這個動作必需的數據。

當然,不同動作所需要的數據也不盡相同,如 “刪除Todo” 動作,我們就需要知道 todo 項的 id,“拉取已有的Todo項” 動作,我們就需要傳入一個元素為 Todo 項對象的數組( todos )。形如 text 、 id 、 todos 這類屬性,我們習慣稱呼其為 “ payload ” 。

現在,我們得到了一個 “栩栩如生” 的動作。它足夠簡潔,但擔任 Model 的 store 暫時還不知道如何感知這個動作從而改變數據結構。

為了處理這個關鍵問題,Reducer 巧然登場。它仍然是一個函數,而且是沒有副作用的純函數。它只接收兩個參數:state 和 action ,返回一個 newState 。

沒錯,state 就是你在 React 中熟知的 state,但根據 Redux 三原則 之一的 “單一數據源” 原則,Reducer 幽幽地說:“你的 state 被我承包了?!?/p>

于是,單一數據源規則實施起來,是規定用 React 的頂層容器組件( Container Components )的 state 來存儲單一對象樹,同時交給 Redux store 來管理。

這里區分一下 state 和 Redux store:state 是真正儲存數據的對象樹,而 Redux store 是協調 Reducer、state、Action 三者的調度中心。

而如此前所說,Reducer 此時手握兩個關鍵信息:舊的數據結構(state),還有改變它所需要的信息 (action),然后聰明的 Reducer 算盤一敲,就能給出一個新的 state ,從而更新數據,響應用戶。下面依然拿 TodoList 舉例:

當接收到一個 action 時,Reducer 從 action.type 識別出該動作是要添加 Todo 項,然后路由到相應的處理方案,接著根據 action.text 完成了處理,返回一個 newState 。過程之間,整個應用的 state 就從 state => newState 完成了狀態的變更。

這個過程讓我們很自然地聯想到去銀行存取錢的經歷,顯然我們應該告訴柜臺操作員要存取錢,而不是遙望著銀行的金庫自言自語。

Reducer 為我們梳理了所有變更 state 的方式,那么 Redux store 從無到有,從有到變都應該與 Reducer 強關聯。

因此,Redux 提供了 createStore 函數,他的第一個參數就是 Reducer ,用以描繪 state 的更改方式。第二個是可選參數 initialState ,此前我們知道,這個 initialState 參數也可以傳給 Reducer 函數。放在這里做可選參數的原因是為同構應用提供便捷。

createStore 函數最終返回一個對象,也就是我們所說的 store 對象。主要提供三個方法: getStatedispatch subscribe。 其中 getState() 獲得 state 對象樹。dispatch(actionCreator) 用以執行 actionCreators,建起從 action 到 store 的橋梁。

僅僅完成狀態的變更可不算完,我們還得讓視圖層跟上 store 的變化,于是 Redux 還為 store 設計了 subscribe 方法。顧名思義,當 store 更新時,store.subscribe() 的回調函數會更新視圖層,以達到 “訂閱” 的效果。

在 React 中,有 react-redux 這樣的橋接庫為 Redux 的融入鋪平道路。所以,我們只需為頂層容器組件外包一層 Provider 組件、再配合 connect 函數處理從 store 變更到 view 渲染的相關過程。

而頂層容器組件往下的子組件只需憑借 props 就能一層層地拿到 store 數據結構的數據了。就像這樣:

至此,我們走了一圈完整的數據流。然而,在實際項目中,我們面臨的需求更為復雜,與此同時,redux 和 react 又是具有強大擴展性的庫,接下來我們將結合以上的主體思路,談談我們在實際開發中會遇到的一些細節問題。

2. 細節 應用目錄

清晰的思路須輔以分工明確的文件模塊,才能讓我們的應用達到更佳的實踐效果,同時,統一的結構也便于腳手架生成模板,提高開發效率。

以下的目錄結構為團隊伙伴多次探討和改進而來(限于篇幅,這里只關注 React 應用的目錄。):

入口文件 app.js 與頂層組件 react/container.js

這塊我們基本上保持和之前思路上的一致,用 react-redux 橋接庫提供的 Provider 與函數 connect 完成 Redux store 到 React state 的轉變。

細心的你會在 Provider 的源碼中發現,它最終返回的還是子組件(本例中就是頂層容器組件 “Container“ )。星星還是那個星星,Container 還是那個 Container,只是多了一個 Redux store 對象。

而 Contaier 作為 業務組件 Wrapper 的 高階組件 ,負責把 Provider 賦予它的 store 通過 store.getState() 獲取數據,轉而賦值給 state 。然后又根據我們定義的 mapStateToProps 函數按一定的結構將 state 對接到 props 上。 mapStateToProps 函數我們稍后詳說。如下所見,這一步主要是 connect 函數干的活兒。

業務組件 component/Wrapper.js 與 mapStateToProps

這兩個模塊是整個應用很重要的業務模塊。作為一個復雜應用,將 state 上的數據和 actionCreator 合理地分發到各個業務組件中,同時要易于維護,是開發的關鍵。

首先,我們設計 mapStateToProps 函數。需要謹記一點: 拿到的參數是 connect 函數交給我們的根 state,返回的對象是最終 this.props 的結構。

和 Redux 官方示例不同的是,我們為了可讀性,將分發 action 的函數也囊括進這個結構中。這也是得益于 bindActions 模塊,稍后我們會講到。

這樣,我們這個函數就準備好履行它分發數據和組件行為的職責了。那么,它又該如何 “服役” 呢?

敏銳的你一定察覺到剛才我們設計的結構中,以 “ params ” 開頭的屬性既沒起到給組件展示數據的作用,又沒有為組件發送 action 的功能。它們便是我們分發以上兩種功能屬性的關鍵。

我們先來看看業務組件 Wrapper :

現在,param 屬性們為我們展示了它扮演的角色:在組件中實際分發數據和方法的快遞小哥。這樣,即使項目越變越大,組件嵌套越來越多,我們也能在 param.js 模塊中,清晰地看到我們的組件結構。需求更改的時候,我們也能快速地定位和修改,而不用對著堆積如山的組件模塊梳理父子關系。

相信你應該能猜到剩下的子組件們怎么取到數據了,這里限于篇幅就不貼出它們的代碼了。

Action 模塊: react/action.js、react/actionType.js 和 react/bindActions.js

在前面的介紹中,我們提到:一個 ActionCreator 長這樣:

而在 Redux 中,真正讓其分發一個 action ,并讓 store 響應該 action,依靠的是 dispatch 方法,即:

交互動作一多,就會變成:

而容易想到:抽象出一個公用函數來分發 action (這里粗略寫一下我的思路,簡化方式并不唯一)

而細心的 Redux 已經為我們提供了這個方法 —— bindActionCreator
所以,我們的 bindActions.js 模塊就借用了 bindActionCreator 來簡化 action 的分發:

不難想象,action 模塊里就是一個個 actionCreator :

為了更好地合作,我們多帶帶為 action 的 type 劃分了一個模塊

react/reducers/ 和 react/store.js

前面我們說到,reducer 的作用就是區別 action type 然后更新 state ,這里不再贅述。可上手實際項目的時候,你會發現 action 類型和對應處理方式多起來會讓單個 reducer 迅速龐大。

為此,我們就得想方設法將其按業務邏輯拆分,以免難以維護。但是如何把拆分后的 Reducer 組合起來呢 Redux 再次為我們提供便捷 —— combineReducers 。

只有單一 Reducer 時,想必代碼結構你也了然:

我們最終得到的 state 結構是:

state

demoAPP

當有多個 reducer 時:

我們最終得到的 state 結構是:

state

demoAPP

reducerB

想必你已經想到更進一步,把這些 Reducer 拆分到相應的文件模塊下:

接著,我們來看 store 模塊:

怎么和想象的不一樣?不應該是這樣嗎:

這里引入 redux 中間件的概念,你只需知道 redux 中間件的作用就是 在 action 發出以后,給我們一個再加工 action 的機會 就可以了。

為什么要引入 redux-thunk 這個中間件呢?

要知道,我們此前所討論的都是同步過程。實際項目中,只要遇到請求接口的場景(當然不只有這種場景)就要去處理異步過程。

前面我們知道,dispatch 一個 ActionCreator 會立即返回一個 action 對象,用以更新數據,而中間件賦予我們再處理 action 的機會。

試想一下,如果我們在這個過程中,發現 ActionCreator 返回的并不是一個 action 對象,而是一個函數,然后通過這個函數請求接口,響應就緒后,我們再 dispatch 一個 ActionCreator ,這次我們真的返回一個 action ,然后攜帶接口返回的數據去更新 state 。 這樣一來不就解決了我們的問題嗎?

當然,這只是基本思路,關于 redux 的中間件設計,又是一個有趣的話題,有興趣我們可以再開一篇專門討論,這里點到為止。

回到我們的話題,經過

這樣包裝一遍 store 后,我們就可以愉快地使用異步 action 了:

這里我們用 promise 方式來處理請求,model.js 模塊如你所想是一些接口請求 promise,就像這樣:

你也可以參閱我們往期介紹的其他方式。

最后,我們再來完善一下之前的流程:

3.結語

Redux 的 API 一只手都能數得完,源碼更是精煉,加起來不超過500行。但它給我們帶來的,不啻是一套復雜應用解決方案,更是 Flux 思想的精簡表達。此外,你還可以從中體會到函數式編程的樂趣。

一千個觀眾心中有一千個哈姆萊特,你腦海里的又是哪一個呢?

本文示例代碼GitHub地址:https://github.com/ikcamp/rea...

參考

《Redux 官方文檔》
《深入 React 技術棧》


iKcamp原創新書《移動Web前端高效開發實戰》已在亞馬遜、京東、當當開售。

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/85137.html

相關文章

  • 解析Twitter前端架構 學習復雜場景數據設計

    摘要:總結本文分析了在采用架構下的數據設計結構,在一個復雜的場景下,希望引起讀者對能有一個更深入的認識。 前幾天刷Twitter,發現Nicolas(Engineering at @twitter. Technical Lead for Twitter Lite)發布了這么一條推文: showImg(https://segmentfault.com/img/remote/1460000009...

    csRyan 評論0 收藏0
  • React Redux 中間件思想遇見 Web Worker 的靈感(附demo)

    摘要:寫在最前原文首發于作者的知乎專欄中間件思想遇見的靈感附,感興趣的同學可以知乎關注,進行交流。其中,最重要的一個便是對多線程的支持。在中提出了工作線程的概念,并且規范出的三大主要特征能夠長時間運行響應理想的啟動性能以及理想的內存消耗。 寫在最前 原文首發于作者的知乎專欄:React Redux 中間件思想遇見 Web Worker 的靈感(附demo),感興趣的同學可以知乎關注,進行交流...

    whatsns 評論0 收藏0
  • 拒絕Redux文檔“毒害” 一個項目告訴你Redux最新真正哲學

    摘要:之前分享過幾篇關于技術棧的原創文章解析前端架構學習復雜場景數據設計干貨總結打造單頁應用一個項目理解最前沿技術棧真諦一個工程實例今天進一步剖析一個實際案例移動網頁版。目前面臨的問題在于提高產品的各方面性能體驗。 之前分享過幾篇關于React技術棧的原創文章: 解析Twitter前端架構 學習復雜場景數據設計 React Conf 2017 干貨總結1: React + ES next ...

    YuboonaZhang 評論0 收藏0
  • React技術實現XXX點評App demo

    摘要:項目的架構也是最近在各種探討研究。還求大神多指點項目技術總結技術棧項目結構探究初體驗關于項目中的配置說明項目簡單說明開發這一套,我個人的理解是體現的是代碼分層職責分離的編程思想邏輯與視圖嚴格區分。前端依舊使用技術棧完成。 項目地址:https://github.com/Nealyang/R...技術棧:react、react-router4.x 、 react-redux 、 webp...

    wslongchen 評論0 收藏0

發表評論

0條評論

最新活動
閱讀需要支付1元查看
<