翻譯:瘋狂的技術宅
做者:Nick Sweeting
英文標題:Shape your redux store like your database
英文原文:https://hackernoon.com/shape-...
說明:本專欄文章首發於公衆號:jingchengyideng 。javascript
使用索引能夠從多個維度表現數據。(此處應爲動圖,請看原文)html
最近我在RC聊天系統瀏覽關於 JavaScript 的一些討論時,注意到了Kate Ray的一個問題:前端
應該怎樣在 redux 存儲中結構話個人數據?java
的確,這是使用 redux 時最多見的問題之一。react
有不少須要考慮的東西,你常常會像訪問一個行列表同樣遍歷數據嗎? 你須要以O(1)的時間複雜度快速訪問某些條目嗎?git
我在實踐中獲得了一些經驗,一般在訪問時間和迭代的難易程度之間作一些權衡。github
若是你須要存儲一些每一個項目都帶有id的數據,可使用Array
, Object
, 或者 對象數組來保存。數據庫
[{values}]
:這是最多見的一種範式。它使迭代變得容易,可是不通過迭代和過濾就不能快速訪問特定條目。redux
categories: [ {name: 'abs', id: '32o8wafe', exercises: ['crunches', 'plank']}, {name: 'arms', id: 'oaiwefjo', exercises: [...]}, {name: 'legs', id: 'aoijwfeo', exercises: [...]}, ]
id
爲索引的對象{id: {values}}
:這種方法能夠是你以O(1)的時間複雜度快速訪問每一個項目,可是在使用object.values()
進行迭代時,不能很容易地訪問給定項目對應的id
。後端
[{id: {values}}]
:這讓你能夠遍歷列表並輕鬆訪問id
和值,可是它作到以O(1)的時間複雜度快速訪問,由於它是一個數組。
categories: [ {32o8wafe: {name: 'abs', exercises: [...]}, {oaiwefjo: {name: 'arms', exercises: [...]}, {3oij2e3c: {name: 'legs', exercises: [...]}, ]
在學習redux的過程當中,我在Monadical偶然發現了一種不一樣的方法,它使咱們受益於簡單的Object.values(state.categories)
,並可以以O(1)的時間複雜度快速對單個項目的訪問:
categories: { 32o8wafe: {id: '32o8wafe', name: 'abs', exercises: [...]}, oaiwefjo: {id: 'oaiwefjo', name: 'arms', exercises: [...] }, 3oij2e3c: {id: '3oij2e3c', name: 'legs', exercises: [...] }, }
請注意id
既是行的鍵,同時也是行自己的屬性。這一點點重複使咱們在訪問時間上有了很大的靈活性。這也與Redux文檔推薦的歸一化(也稱扁平)模型兼容。
如今你能夠遍歷數據了,也能夠在迭代時訪問id
!
Object.values(categories).map(cat => ({id: cat.id, name: cat.name}))
或者經過id
快度訪問任何項目!
categories[category_id].name
咱們將這樣組織好的數據發送到前端,前端就不須要作任何處理來生成id: values
映射,從而也就減小了錯誤的產生。在後端很容易作到這一點,由於你極可能從數據庫中提取數據,而數據庫中已經存在id
字段,能夠直接將其做爲鍵使用。
請注意,咱們上面介紹的結構只是一些行的索引,索引是id
。你也能夠這樣設計本身的存儲結構:使用你想要用的字段生成索引,來達到O(1)的時間複雜度進行快速訪問
categories_by_name = { abs: '32o8wafe', arms: 'oaiwefjo', legs: '3oij2e3c', } const get_category_by_name = (store, name) => store.getState().categories[categories_by_name[name]]
也能夠爲一樣的數據構建儘量多的索引,這樣將使你在任何列上基於O(1)的速度進行訪問,就像在數據庫中同樣。
把你存儲的數據想象成爲圖書館,能夠用索引快速找到任何項目(此處應爲動圖,請看原文)
這裏描述的模式正是Normalizr庫所使用的模式。若是你想把你的數據扁平化(按類型分開),就像我前面介紹的索引概念同樣,請閱讀Normalizr的文檔《Redux Without Profanity docs》。
Redux 和 Normalizr 與 Reselect 配合的也很好,若是你關心性能,而且喜歡有一箇中央列表的記憶選擇器,能夠關注一下。
歡迎掃描二維碼關注公衆號,天天推送我翻譯的技術文章。