摘要:之旅時(shí)間作者三月懶驢入門配置文章鏈接之旅鏈接前言上一篇文章,很簡(jiǎn)單的用代碼來(lái)說(shuō)明了,,,各自的意義和相互的聯(lián)系以及在實(shí)際開發(fā)的應(yīng)用。分割你的,使每一個(gè)更有意義,之后再合并回來(lái)。分割和合并和不同。的只有一個(gè)只有一個(gè)就意味著只有一個(gè)。
Redux之旅-2
1. 前言時(shí)間:2016.4.22-11:24
作者:三月懶驢
入門配置文章:鏈接
Redux之旅-1:鏈接
上一篇文章,很簡(jiǎn)單的用代碼來(lái)說(shuō)明了State,Action,Reducer,Store各自的意義和相互的聯(lián)系以及在實(shí)際開發(fā)的應(yīng)用。但是在現(xiàn)實(shí)開發(fā)環(huán)境用,我們的需求不僅僅上一篇文章那么簡(jiǎn)單的。為了應(yīng)付這些復(fù)雜的開發(fā)環(huán)境,我們還需要用到以下這些東西:
Action Creator / bindActionCreators:動(dòng)態(tài)去生成Action。
combineReducers:分割你的reducers,使每一個(gè)reducer更有意義,之后再合并回來(lái)。
applyMiddleware / createStoreWithMiddleware:往store里面添加中間件。使得它的功能更加強(qiáng)大。
很明顯,我們將要學(xué)習(xí)的這三個(gè)功能,對(duì)應(yīng)回上一篇文章的Action,reducer,store。你可以認(rèn)為這是它們各自的一些擴(kuò)展。
2. 新的需求在上一篇文章我們的需求很簡(jiǎn)單。就是一個(gè)按鈕,點(diǎn)擊就讓數(shù)字遞增,那么今天為了學(xué)習(xí)新的東西,我們就增加一些新的需求。我們需求加兩個(gè)按鈕,一個(gè)按鈕就是點(diǎn)擊數(shù)字是+2,一個(gè)按鈕是切換數(shù)字顏色。那么為了更方便我們的開發(fā),我們的開發(fā)目錄也應(yīng)該修改一下。
主要寫代碼的還是在app這個(gè)文件夾里面,里面的目錄分布
component -->放置組件的
index.js
redux -->放置redux
action -->action相關(guān)的
types.js
creator.js
reducer -->reducer相關(guān)的
rootReducer.js
increaseReducer.js --> 處理增加按鈕用的
themeReducer.js --> 處理切換主題按鈕用的
store -->store相關(guān)的
store.js
index.js -->把組件和store connect在一起生成一個(gè)新組件
main.js -->程序入口
3. Action Creator 3.1 為什么需要Creator在Redux之旅-1里面,我們創(chuàng)建了一個(gè)很簡(jiǎn)單的例子:點(diǎn)擊按鈕遞增。那么在更多的時(shí)候,我們的開發(fā)需求是很復(fù)雜的。那么增加一個(gè)點(diǎn)擊就+2的按鈕。這時(shí)候我們要怎么做?
還記得我們上次定義的Action是這樣的:
let IncreaseAction = {type:"increase"}
其中字符串increase的意思就是增加,那么我們現(xiàn)在的需求里面,一個(gè)點(diǎn)擊+2的按鈕,也符合increase這個(gè)意思。這時(shí)候的Action就不能像之前那樣,直接寫死。因?yàn)閷懰懒司蜎]辦法讓reducer知道,這個(gè)Action是+1還是+2了!而需要引入一個(gè)新的概念:Action Creator
let IncreaseAction = (num = 1)=>{ return{ type:"increaseAction", num //看注1 } }
注1:這里用到了ES6的新語(yǔ)法,增強(qiáng)字面量。具體看文章最后的注釋
上面就是一個(gè)Action Creator,聽起來(lái)很高大上的英文名詞,其實(shí)就是一個(gè)幫我們返回Action的函數(shù)。那還記得Action的本質(zhì)其實(shí)是什么嗎?一個(gè)我們規(guī)定最了低限度要帶著type屬性的對(duì)象。那么其實(shí)就很簡(jiǎn)單了。Creator每次幫我們生成type都是increaseAction,但num不同的Action出來(lái)。這樣,reducer就能分辨出我們的這個(gè)Action要+1還是+2
3.2 代碼實(shí)現(xiàn)文件位置: app/redux/action/types.js
//為了更加直觀,我們把每個(gè)Action的type屬性的值額外用一個(gè)文件去描述 export const INCREASE = "increase" //增加數(shù)字的 export const THEME = "theme" //切換主題的
文件位置: app/redux/action/creator.js
import * as types from "./types" export let increaseAction = (num = 1)=>{ return { type:types.INCREASE, num } } export let themeAction = ()=>{ return { type:types.THEME, } }
OK!上面的代碼中,我還順便把切換主題的Action也寫了,雖然它不需要傳入?yún)?shù)去處理,但是為了以后的拓展性,用Action Creator總比用寫死了的Action更佳,畢竟產(chǎn)品經(jīng)理要改需求,誰(shuí)也擋不住。
4. combineReducers 4.1 分割和合并和Flux不同。Redux的store只有一個(gè)!只有一個(gè)store就意味著只有一個(gè)state。那么我們?cè)O(shè)計(jì)state的時(shí)候就很會(huì)糾結(jié)了。像現(xiàn)在這樣子:
let state = { count:0, //增加數(shù)字 theme:"#ffffff" //主題顏色 }
這并不是一個(gè)理想的state。一個(gè)理想的state應(yīng)該要設(shè)計(jì)得很純粹。不應(yīng)該把無(wú)關(guān)得兩個(gè)東西交錯(cuò)在一起。因?yàn)?,我們需要分割開我們的reducer。每個(gè)不同的reducer下面僅僅處理自己擁有的state.
let CountState = { count:0, //增加數(shù)字 } let ThemeState = { theme:"#ffffff" //主題顏色 }
這樣的話,我們的state就可以設(shè)計(jì)得很小,并且很純粹。而作為匯總,我們會(huì)用combineReducers把這些reducers合并回來(lái)。實(shí)際上state還是一大塊,但是在reducer的角度來(lái)看,每個(gè)reducer都指示一小塊。
4.2 代碼實(shí)現(xiàn)文件位置: app/redux/reducer/increaseReducer.js
//處理數(shù)字增加的reducer import * as types from "../action/types" let reducer = (state={count:0},action)=>{ let count = state.count switch(action.type){ case types.INCREASE: //注意這里使用的action.num,明白是從哪里來(lái)的嗎? return {count:count+action.num} break default: return state } } export default reducer
文件位置: app/redux/reducer/themeReducer.js
//處理主題的reducer import * as types from "../action/types" const writeColor = "#ffffff" const grayColor = "#cccccc" let reducer = (state={color:writeColor},action)=>{ let count = state.count switch(action.type){ case types.THEME: if(state.color == writeColor){ return {color:grayColor} } else { return {color:writeColor} } break default: return state } } export default reducer
文件位置: app/redux/reducer/rootReducer.js
//合并兩個(gè)reducer import { combineReducers } from "redux" import Increase from "./increaseReducer" import Theme from "./themeReducer" const rootReducer = combineReducers({ Increase, Theme }) export default rootReducer5. Middleware 5.1 什么叫做中間件
在這里我并不打算深入去描述中間件這種概念,如果你是做node開發(fā)的話,又剛好用上了KOA的話,你會(huì)對(duì)這個(gè)東西很熟識(shí)。那么這里我簡(jiǎn)單的介紹一下什么是中間件。
你可能認(rèn)為它是一個(gè)使用包含自定義功能的(可以讓你包裝 store 的 dispatch 方法來(lái)達(dá)到你想要的功能),用來(lái)擴(kuò)展 Redux 是一種方式。
在這里,有兩個(gè)中間件是推薦使用的。
//用來(lái)打log的,開發(fā)時(shí)候用很方便 npm install --save-dev redux-logger //這個(gè)會(huì)在異步Action的時(shí)候用到,這篇文章沒有到,不細(xì)說(shuō)。 npm install --save redux-thunk
5.2 代碼實(shí)現(xiàn)注2:thunk,推薦閱讀阮一峰老師的Thunk 函數(shù)的含義和用法
文件位置: app/redux/store/store.js
"use strick" import {createStore,applyMiddleware} from "redux" import createLogger from "redux-logger" import rootReducer from "../reducer/rootReducer" /* 以前創(chuàng)建store的方式: let store = createStore(reducers) */ let createStoreWithMiddleware = applyMiddleware( createLogger(), )(createStore) let store = createStoreWithMiddleware(rootReducer) export default store6. 連接組件和redux
這里面和以前的差不多,但又有一些細(xì)節(jié)上的東西,我們需要注意的
文件位置: app/redux/index.js
"use strict" import React from "react" //注意這里引入:bindActionCreators import { bindActionCreators } from "redux" import { Provider,connect } from "react-redux" //這里引入了組件 import Index from "../component/index" //引入了action creator 和 store。為啥沒有引入reducer? //因?yàn)閞educer在上面創(chuàng)建store的時(shí)候已經(jīng)用到了 import * as actions from "./action/creator" import store from "./store/store" let {Component} = React /* mapStateToProps里面需要注意的是,由于我們的reducer是合并起來(lái)的,因此我們的state也是幾個(gè)state拼起來(lái)。至于是哪幾個(gè)state拼起來(lái)? 可以看回去rootReducer.js里面combineReducers的時(shí)候,里面的對(duì)象名字就是這里state的名字。 當(dāng)然這里的return可以寫成:return {state}也沒所謂。但是為了大家能認(rèn)清這個(gè)state里面有什么東西,這里寫的稍微復(fù)雜一點(diǎn) */ let mapStateToProps = (state) =>{ //return {state} return { reduxState:{ Increase:state.Increase, Theme:state.Theme, } } } /* mapDispatchToProps里面用到了bindActionCreators。關(guān)于bindActionCreators的作用看下面注釋3 */ let mapDispatchToProps = (dispatch) =>{ return{ reduxActions:bindActionCreators(actions,dispatch) } } let Content = connect(mapStateToProps,mapDispatchToProps)(Index) class App extends Component{ render(){ return} } export default App
7. 組件開發(fā)注3: bindActionCreators(actionCreators, dispatch):是把 action creators 轉(zhuǎn)成擁有同名 keys 的對(duì)象,而使用 dispatch 把每個(gè) action creator 包圍起來(lái),這樣可以直接調(diào)用它們。
關(guān)于redux的開發(fā)在上面已經(jīng)完成了,現(xiàn)在進(jìn)入的是組件的開發(fā),這里面更多的是滿足例子而寫的。沒有太多的現(xiàn)實(shí)開發(fā)價(jià)值。但是我們可以在這里面很好的觀察,我們寫好的程序是怎樣工作的。
文件位置: app/component/index.js
"use strict" import React from "react" let {Component} = React class Index extends Component{ constructor(props){ super(props) } //點(diǎn)擊增加按鈕事件 _addHandle(num){ /* 這里面可以想一下increaseAction的名字是怎么來(lái)的,同樣下面主題切換按鈕事件的themeAction又是怎么來(lái)的,代碼之后為你揭秘。 */ let {increaseAction} = this.props.reduxActions increaseAction(num) } //主題切換按鈕事件 _ThemeHandle(){ let { themeAction } = this.props.reduxActions themeAction() } render(){ //這里面輸出props看看里面有什么東西 //console.log(this.props) let { reduxState } = this.props return () } } //樣式定義,不用細(xì)看 const styles = { circle:{ width:"400px", height:"400px", position:"absolute", left:"50%", top:"50%", margin:"-200px 0 0 -200px", borderRadius:"50px", fontSize:"60px", color:"#545454", backgroundColor:"#ececec", lineHeight:"100px", textAlign:"center", }, btnAddOne:{ width:"100px", height:"50px", lineHeight:"50px", backgroundColor:"#fcfcfc", fontSize:"20px", position:"absolute", left:"40px", bottom:"10px", cursor:"pointer", }, btnAddTwo:{ width:"100px", height:"50px", lineHeight:"50px", backgroundColor:"#fcfcfc", fontSize:"20px", position:"absolute", right:"40px", bottom:"10px", cursor:"pointer", }, btnTheme:{ width:"80%", height:"50px", lineHeight:"50px", backgroundColor:"#fcfcfc", fontSize:"20px", position:"absolute", right:"10%", bottom:"100px", cursor:"pointer", } } export default Index{reduxState.Increase.count}切換主題{this._addHandle(1)}}>+1{this._addHandle(2)}}>+2
需要注意:在redux里面action/creator/reducer/store各種定義太多了。有時(shí)候你很難找到這個(gè)東西的名稱是哪里定義過(guò)來(lái)的感覺。輸出組件的props的話,我們得到這么一個(gè)東西
{ reduxAction:{ increaseAction:fn(), themeAction:fn(), }, reduxState:{ Increase:count, Theme:color, } }
reduxAction:來(lái)自redux/index.js里面,我們mapDispatchToProps的時(shí)候return 的一個(gè)對(duì)象時(shí)候自己定義的一個(gè)對(duì)象名字
increaseAction:fn()/themeAction:fn():因?yàn)閎indActionCreators的轉(zhuǎn)化造成的和creator的同名函數(shù)。因此這兩個(gè)函數(shù)的名稱定義出自redux/action/creator.js
reduxState:來(lái)自redux/index.js里面,我們mapStateToProps的時(shí)候return 的一個(gè)對(duì)象時(shí)候自己定義的一個(gè)對(duì)象名字
Increase/Theme 也是在mapStateToProps里面自己定義的。
這里順便貼出入口文件
文件位置: app/main.js
"use strict" import "babel-polyfill" import React from "react"; import { render } from "react-dom" import App from "./redux/index"; render(, document.getElementById("main") );
如果沒有做錯(cuò),我們的程序能跑起來(lái),如同下圖一般
而控制臺(tái)會(huì)在每次按鈕之后,會(huì)如同下圖一樣
8. 總結(jié)和上一次說(shuō)明state/Action/reducer/store的各種比如不同,這次需要說(shuō)的分別是Action/reducer/store的一些擴(kuò)展,為了更好的寫程序,這些擴(kuò)展是必不可少的,但會(huì)給新手一種把程序切割得很零散從而無(wú)從下手得感覺。所以這次我更加偏重于說(shuō)明,每一個(gè)擴(kuò)展存在得意義以及代碼得實(shí)現(xiàn),希望大家能看懂。
9.一些ES6的小知識(shí)在3.1的注1的時(shí)候,我們說(shuō)了一個(gè)ES6的新特性:字面量增強(qiáng)
ES6里面我們定義一個(gè)對(duì)象的時(shí)候
let c = "abc" let obj = { a, //這個(gè)叫做鍵名簡(jiǎn)寫 b(){ //這個(gè)是函數(shù)定義的簡(jiǎn)寫 .... }, [c]:12 // 這個(gè)是自定義鍵值寫法,一個(gè)很有趣的語(yǔ)法糖 }
等于號(hào)后面我們叫做 字面量
以上代碼等價(jià)于以下
let obj = { a:a, b:function(){ .... }, abc:12 }
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/79478.html
摘要:我們約定,內(nèi)使用一個(gè)字符串類型的字段來(lái)表示將要執(zhí)行的動(dòng)作。多數(shù)情況下,會(huì)被定義成字符串常量。要進(jìn)去工廠加工產(chǎn)品,就得帶上相應(yīng)得鑰匙,不同的鑰匙對(duì)應(yīng)工廠中上不同的生產(chǎn)線里面的函數(shù),從而有不同的產(chǎn)出改變之后的 時(shí)間:2016.4.7-17:24作者:三月懶驢入門配置文章:鏈接 準(zhǔn)備 在你的項(xiàng)目下面加入redux / react-redux npm install redux --s...
摘要:一其實(shí)是一個(gè)比較輕便的可擴(kuò)展的狀態(tài)管理工具,是一個(gè)由以及一些其他團(tuán)隊(duì)的人共同維護(hù)的開源項(xiàng)目。當(dāng)應(yīng)用公共狀態(tài)的組件在狀態(tài)發(fā)生變化的時(shí)候,會(huì)自動(dòng)完成與狀態(tài)相關(guān)的所有事情,例如自動(dòng)更新自動(dòng)緩存數(shù)據(jù),自動(dòng)通知等。 一、MobX MobX其實(shí)是一個(gè)比較輕便的可擴(kuò)展的狀態(tài)管理工具,是一個(gè)由Facebook以及一些其他團(tuán)隊(duì)的人共同維護(hù)的開源項(xiàng)目。 當(dāng)應(yīng)用公共狀態(tài)的組件在狀態(tài)發(fā)生變化的時(shí)候,會(huì)自動(dòng)完...
摘要:原文地址我想分享一些文章,來(lái)幫你學(xué)習(xí)的概念和架構(gòu)在開始之前我們先來(lái)看這兩篇文章,用代替和然后我們通過(guò)一個(gè)代碼教程我翻譯地址深入了解,然后看一看超級(jí)介紹完成你對(duì)的探索之旅現(xiàn)在是時(shí)候去學(xué)習(xí)和再往前走理解并且看一看關(guān)于的一切注盡量中文地址的我用的 原文地址 我想分享一些文章,來(lái)幫你學(xué)習(xí)redux的概念和架構(gòu) 在開始redux之前我們先來(lái)看這兩篇文章,用High Order Component...
摘要:到月底了,小明的爸爸的單位發(fā)了工資總計(jì)塊大洋,拿到工資之后第一件的事情就是上交,毫無(wú)疑問(wèn)的,除非小明爸爸不要命了。當(dāng)小明的爸爸收到這個(gè)通知之后,心的一塊大石頭也就放下來(lái)了。下面我們正式開始我們的源碼閱讀之旅。 前言 用過(guò)react的小伙伴對(duì)redux其實(shí)并不陌生,基本大多數(shù)的React應(yīng)用用到它。一般大家用redux的時(shí)候基本都不會(huì)單獨(dú)去使用它,而是配合react-redux一起去使用...
摘要:引入,有效解決事件分發(fā)時(shí),事件類型的一致性以及清晰邏輯性。其實(shí),細(xì)心思考,不難發(fā)現(xiàn),隨著項(xiàng)目增大。目錄將會(huì)隨著數(shù)據(jù)處理事件迅速膨脹。大家一直維護(hù)著這個(gè)事件命名機(jī)制,身心疲憊有木有。其實(shí),隨著項(xiàng)目增大,獨(dú)立出來(lái)的也會(huì)導(dǎo)致非常麻煩的維護(hù)問(wèn)題。 作者:Jogis原文鏈接:https://github.com/yesvods/Blog/issues/4轉(zhuǎn)載請(qǐng)注明原文鏈接以及作者信息 前言 事情...
閱讀 2217·2021-09-09 09:33
閱讀 1166·2019-08-30 15:43
閱讀 2736·2019-08-30 13:45
閱讀 3360·2019-08-29 11:00
閱讀 993·2019-08-26 14:01
閱讀 3635·2019-08-26 13:24
閱讀 545·2019-08-26 11:56
閱讀 2757·2019-08-26 10:27