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