摘要:而且關聯關系只需要定義一次就可以了,不需要重復定義。更新狀態主要是用來更新,響應并發送到的引用狀態變化。不能夠在中傳遞參數執行有副作用的操作以及調用非純函數。主要是讓容器組件拿到。
Redux-ORM理解之實現Todo List 一、概念
redux-orm及其作用:
redux-orm主要是用來管理我們的state數據,當一個項目比較大,邏輯結構比較復雜,每個數據之間都有聯系,此時便需要將這些state進行統一管理,redux-orm就是用來解決這些數據間的關聯問題,所以redux-orm就像一個關系型數據庫,而每個對象類型就像是數據庫中的數據表,并且是以JavaScript的對象形式存儲這些數據的。
那么也就是說,當項目的中涉及到的對象類型并不很多,且對象類型之間的關聯性不大的時候,并不建議使用redux-orm,如果項目足夠簡單,連redux也不需要使用到。
在todo list 實現的基本功能有:
選擇用戶
創建todo
標記todo完成
刪除todo
創建tag標簽
移除tag標簽
所以按照上面的功能,可以將todo list分為三張表,分別是user(用戶表)、todo表和tag標簽表,這些表就相當于一個實例,每個實例都會有自己的行為屬性和方法
User:
屬性:id、 name
行為:selectUser
Todo:
屬性:id、text(todo內容)、done(標記結束)、user、 tags
行為: createTodo、markDone、deleteTodo
Tag:
屬性: name
行為: addTagToTodo、 removeTagFromTodo
State是一個對象,是用來描述應用。在這個todo list中,當需要有一個對象用來描述
Action是把數據從應用傳到store的有效載荷,它是store數據的唯一來源。其本質上是JavaScript普通對象,action內必須使用type字符串類型,type表示將要執行的動作,在多數情況下,type被已定義為字符串常量。
Action創建函數就是生成action方法,該方法只是簡單的返回一個action。例如,對于添加標簽這個action是這樣執行的,先創建一個addTagToTodo的方法,該方法接收tag和todo兩個參數,然后將其返回為一個對象,其中對象的屬性值中必須有一個type
export const addTagToTodo = (todo, tag) => { return { type: ADD_TAG_TO_TODO, payload: { todo, tag, }, }; };
在ORM中定義了一個Model類來將實體類關聯起來, 對于Todo這個實體類來說,通過ES6類語法進行定義,并繼承了ORM的Model類。
Model需要設置名稱才可以識別到對應的數據,以及實體類與其他數據關聯的方式。
對于Todo類來說,它跟User只能是一對多,一個User下有多個Todo,而跟tag可以多對多,一個Todo可以有多個tag,通用一個tag可以存在在多個Todo中,所以Model類中的fields主要是用了來定義當前實體類與其他類的關聯關系,這些如:fk、many、oneToOne接收兩個參數,第一個是被關聯的實體類,就是在Model中定義的modelName和操作的類名。 而且關聯關系只需要定義一次就可以了,不需要重復定義。
最后要實現實體類間的關聯必須將其注冊到Schema()方法中并導出,這樣才能夠真正關聯其實體間的關系。當實體類比較多的情況下,可能需要一個多帶帶的文件來存放這些需要注冊的實體類,這樣可以使項目模塊化更易于管理。
import { Schema, Model, many, fk } from "redux-orm"; import { CREATE_TODO, MARK_DONE, DELETE_TODO, ADD_TAG_TO_TODO, REMOVE_TAG_FROM_TODO, } from "./actions"; export class Todo extends Model { static reducer(state, action, Todo, session) { const { payload, type } = action; switch (type) { case CREATE_TODO: const tagIds = action.payload.tags.split(",").map(str => str.trim()); const props = Object.assign({}, payload, { tags: tagIds, done: false }); Todo.create(props); break; case MARK_DONE: Todo.withId(payload).done = true; break; case DELETE_TODO: Todo.withId(payload).delete(); break; case ADD_TAG_TO_TODO: Todo.withId(payload.todo).tags.add(payload.tag); break; case REMOVE_TAG_FROM_TODO: Todo.withId(payload.todo).tags.remove(payload.tag); break; } } } Todo.modelName = "Todo"; Todo.fields = { tags: many("Tag", "todos"), user: fk("User", "todos"), }; export const schema = new Schema(); schema.register(Todo); export default schema;
Reducers主要是用來更新state,響應actions并發送到store的引用狀態變化。
在Redux應用中,所有的state都被保存在一個單一對象中。
reducer是一個純函數,接收舊的state和action,返回新的state。不能夠在reducer中傳遞參數、執行有副作用的操作以及調用非純函數。只需單純地執行計算就可以,其更新是局部的,只有當當前的reducer中的數據發生改變后,reducer才會重新進行計算。
在Redux-ORM中使用特定reducers的模型來操作數據。首先在Model類中先定義一個靜態的reducer方法,它會接收所有需要更新的action。如果沒有定義reducers的話,ORM會直接使用默認方法去實現更新。
其原理是,在靜態的reducer方法中接收四個參數:state(狀態)、action(當前操作)、Todo(模型類)、session(ORM的會話實例)。在Todo的reducer中,通過對當前Todo的type進行循環遍歷來執行對Todo的增加、刪除、修改等操作,而session這個會話實例參數主要是用來訪問和查詢其他Model,但是不建議在當前的Model修改其他Model中的數據。
在Redux-ORM中的seletors是使用了了第三方插件reselect
selector在ORM中可以計算派生數據,其在整個ORM中一直是有效的,跟reducer一樣,只要其接收的參數發生改變就會觸發該方法,而且selector是可組合的,可以作為其他seletor的輸入
export const todos = createSelector( ormSelector, state => state.selectedUserId, schema.createSelector((orm, userId) => { return orm.Todo.withRefs.filter({ user: userId }).map(todo => { const obj = Object.assign({}, todo.ref); obj.tags = todo.tags.withRefs.map(tag => tag.name); return obj; }); }) );
首先使用createSelector方法創建了todo的選擇器,該方法中的第一個參數始終是orm的selector,然后對input selector進行回調,回調是用過schema創建了createSelector方法來計算關聯的數據然后并返回。
在todo的seletor中,通過與selectedUserId中進行關聯,當被選中的userId發生變化時就會觸發該方法,并過濾出該user下的所有Todo數據及該Todo下的tag數據并返回。
當我們將所有的數據都定義好了之后,就需要在視圖中去使用
首先,在入口文件導入redux中的createStore、combineReducers、applyMiddleware、Provider還有redux中的createLogger等方法
createStore:該函數主要是用來生成store, store就是保存數據的地方,相當于一個容器,整個項目中只能有一個store
combineReducer:主要是用于Reducer的拆分,其可以將拆分的各個子reducer函數通過該方法合成一個大的Reducer
applyMiddleware、createLogger都是redux的中間件,主要是用來執行異步操作。其中createLogger是redux-logger模塊中的方法,是生成redux日志,并打印在控制臺,該方法是放在applyMiddleware方法中。
Provider: 主要是讓Store容器組件拿到state。
最后,可以使用redux中的connect()方法將UI組件和store容器組件連接起來,主要依靠輸入與輸出來實現。
輸入(mapStateToProps)是將store中的數組轉化為UI組件的參數。 其是一個函數,建立一個從state對象到UI組件props對象的映射關系,其執行后返回一個對象,里面的每個鍵值對就是一個映射
輸出(mapDispatchToProps)是用戶發出的動作轉變成Action對象,從UI組件傳出去。它定義哪些用戶的操作應該當做Action并傳給Store,它個可以是一個函數,也可以是一個對象。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/96365.html
摘要:但還存在一些問題,比如,單向數據流導致的有時數據鏈過長過繁瑣所以才產生了,需要在多地保存同一份數據等等。數據流細粒度的目前來說,我們的的甚至是還是設計得太過簡單。 前言 ??由于筆者對React的了解不深,即便算是學習React的時間,到目前也才剛剛半年,所以錯誤不足之處還望指正。以下都是基于React 15(可能有些是16),webpack1進行探討(注:未學習過Vue,Ng,Emb...
摘要:前言最近在學習框架的基本原理,看了一些技術博客以及一些對源碼的簡單實現,對數據代理數據劫持模板解析變異數組方法雙向綁定有了更深的理解。 前言 最近在學習vue框架的基本原理,看了一些技術博客以及一些對vue源碼的簡單實現,對數據代理、數據劫持、模板解析、變異數組方法、雙向綁定有了更深的理解。于是乎,嘗試著去實踐自己學到的知識,用vue的一些基本原理實現一個簡單的todo-list,完成...
摘要:前言在學習組件化開發的時候,自己雖然也能編碼實現,但如果不做筆記,只是寫代碼,學習的效果還不夠好。為組件準備好數據之后,就可以開始用它了。新增的代碼如下上面是組件新增的代碼,用戶點擊按鈕之后,會執行該組件內的函數。 前言 在學習 Vue.js 組件化開發 Todo List 的時候,自己雖然也能編碼實現,但如果不做筆記,只是寫代碼,學習的效果還不夠好。只有把自己的實現思路記錄下來,遇到...
摘要:網絡上大多數文章,也是千篇一律的翻譯這句話,可是僅憑這一句話,我想象不到的使用場景。因為真正的使用場景下,子組件的數據都是來自父組件的。組件的數據都是來自調用者的,然后會把每一行的,在開發者需要時,傳遞出去。 Vue的slot-scope的場景的個人理解 這篇文章不是單純把文檔的話和api拿來翻譯和演示,而是談談我對于slot-scope的使用場景的個人理解,如果理解錯誤,歡迎討論! ...
摘要:數據結構之應用之常用命令之應用場景說明本文參考了開發實戰指南,還有實戰自己之前的筆記。我們正式進入主題吧,中種數據結構的使用場景介紹。應用場景土法建索引。此命令會覆蓋哈希表中已存在的域。 數據結構之Redis應用之常用命令之應用場景 說明 1、本文參考了Redis開發實戰指南GitBook,還有《Redis實戰》自己之前的筆記。主體框架來自這里。 2、感謝大佬們的付出,在這里自己只是...
閱讀 2885·2021-10-14 09:50
閱讀 1230·2021-10-08 10:21
閱讀 3663·2021-10-08 10:16
閱讀 3070·2021-09-27 14:02
閱讀 3146·2021-09-23 11:21
閱讀 2134·2021-09-07 10:17
閱讀 416·2019-08-30 14:00
閱讀 2121·2019-08-29 17:26