Redux让我脑仁疼,感受搞不定他。由于Redux对我而言太抽象了,因此我用通俗易懂地方法去思考Redux,感受可以理解Redux一些了。node
本文要点:git
本文代码仓库,在此文件夹之中。es6
讲道理我要用import和export的写法来学习Redux,可是node有些es6仍是不支持的,为了简单演示,我就用requre和module.exports来演示。(否则我还得讲解下babel转换es6的知识点)github
在开始以前,咱们是否是应该安装一个redux,而后才能开始愉快地玩耍。npm
npm install --save redux
复制代码
用Redux建立全局应用数据管理store
以前,咱们须要建立两个类型的JS文件,一个是action
一个是reducer
,这两个类型的功能我我的认为很容易搞混。不知道哪一个是干什么,常常忘记用法。那我只能经过他们的具体含义来判断他们的用法,而不是死记硬背(哎,年纪大了,记性很差,只能经过理解来记住了。)redux
首先咱们先看action
,相信这个单词你们都认识。导演拍戏的时候,都喜欢说action!
,这个既有行动的意思,也有开始的意思,在Redux中就是开始行动的意思。也就是说这个action是主动,而非被动的。导演说开始,你就要开始,并且还要按照剧本进行,一切都被安排地明明白白。因此,Redux的action,就是一个指示,告诉store,我要进行这个东西,你给安排下。有时候,咱们须要附带点内容到store,才能进行下一步操做,这个时候就须要action携带规范的参数。数组
因此咱们怎么写action呢?包含两点:bash
注册行为,安排行为,标准每一个行为的指令babel
const todo={
TOGGLE_TODO:'TOGGLE_TODO',
GET_TODOS:'GET_TODOS'
}
复制代码
配置行为所带的参数,标准化参数,该带上的都带上,以避免被退回。其中type
是行为的类型,必须有,就像有些office要带门卡同样,忘了就再见!要被保安请出去的。后方的item
就是自定义的,看看你的操做须要哪些参数,须要就带上,不须要带上的就不要带上了,哪样就很累赘了。异步
const todo={
TOGGLE_TODO:'TOGGLE_TODO',
GET_TODOS:'GET_TODOS',
toggleTodo:function ({ items,id }) {
return {
type: todo.TOGGLE_TODO,
items:items
id:id
}
},
getTodos: function getTodos({items}){
return {
type:todo.GET_TODOS,
items:items
}
}
}
module.exports=todo
复制代码
action只是告诉你发生了什么,给你配齐了参数,可是不执行,不对传入的对象(state)进行改变。*
可是既然action仅仅是配置而已,那么怎么操做呢,以后怎么进行呢?Redux才不会这么好心帮咱们把后续操做给搞定了,这个时候咱们就要去研究Reducer了,一个我不知道如何翻译的函数。
如今咱们来看最没法理解的reducer
,为何他要叫reducer
,有什么具体含义吗?仍是随便起的名字,总有一个缘由吧,就和爸妈给咱们取名字同样老是寄予一些美好的期盼。
reducer
的含义有不少,不少领域都用这个单词,可是在Redux中,这应该是函数式语言(functional languages)
中的一个概念。在wiki中,一般称为Fold,做为一个结构转变(structural transformations)的一个方式。
其余语言Reducer实现方式咱们无论,咱们只看JS,在JS中出现的array.reduce(func,initval)
,相信你们应该很熟悉,也是一个刚上手就想哭的一个方法。数组中的reduce
有什么特色呢(不会用reduce的小伙伴,点击这里):
initval
func
方法,这个方法必须是纯函数,既不改变传入对象的属性array
保持不变。从而能够推论出Redux中的reducer
的特色:
state
你们可能对纯函数(pure funciton)
有些模糊,函数还能pure??觉得是纯牛奶呢??这里的pure的意思就是他是干干净净的,毫无杂质。也就是一下两点:
你们想深刻了解的话,双手奉上wiki连接。
那么咱们该怎么写呢?
你们复习下上面的action,reducer但是action配套的好兄弟,一个在前,一个在后并肩做战。
reducer并非主动执行,而是被动执行的,来了一个action,而后reducer处理下。
简而言之:reducer就是响应来自action的召唤,而后返回一个新的对象(state)。
首先先导入来自action的行为,这行为是被注册的,是能够执行的。
const {TOGGLE_TODO,GET_TODOS}=require('../actions/Todo')
复制代码
reducer的一个定义就是必定有个初始值,这里设置一个也就是以防万一。
const initialState={}
复制代码
重点来了,reducer开始过滤注册的行为们,而后每次都是一个个配对,赶上配对的,就执行对应的代码,而后返回一个新的state
,若是轮了一边发现这是未注册的行为,为了防止这个行为回去很差交代,就把原始的state
给他带回去交差。
module.exports=function(state = initialState, action) {
switch(action.type){
case GET_TODOS:
return {todos:[...action.items]}
case TOGGLE_TODO://deleted=true
return {
todos:action.items.map((i)=>{
if(i.id===action.id){
return {
...i,
status:i.status===0?1:0
}
}else{
return {
...i
}
}
})
}
default:
return state;
}
}
复制代码
reducer根据action的指令,进行一系列操做,可是不改变原有的传入对象(state),而是返回一个新的对象(state)。也就是Reducer,进行纯计算,没有异步,没有污染,出来的值没有意外,就像1+1必定等于2同样,而后返回一个崭新崭新的对象(state)!
虽action和reducer是一对基,配合默契,可是他们都是两个独立的模块,怎么酱他们连接起来,还须要一个桥梁。这个就是store
,redux中真正的老大,你们都要经过store来执行下一步的人任务,以及要遵从store派发下来的任务。
咱们先配置一个老大吧,todoDemoList
是假数据,你们懂的测试用。老大只须要reducers这群小弟来建帮派createStore
。action再帮派创建之初并没有用处。
const {createStore}= require('../../node_modules/redux')
const todo = require('./reducers/Todo')
const {toggleTodo,getTodos} = require('./actions/Todo')
let todoDemoList=(new Array(20)).join("|").split("|").map((v,i)=>{
return {id:i,content:"demo"+(i+1),status:i%4===0?1:0}
})
const store=createStore(todo)
复制代码
咱们的store究有何种能立呢?
掌控整个应用的数据state
,老大固然是掌控全局的啦,没有什么能瞒住他
若是想要访问应用数据state
,那么就要给store提申请,这个申请就是getState()
console.log(store.getState())//打印出来是一个空的{},固然啦!咱们都没有给老大进贡,拿来的数据
复制代码
dispatch(你的申请action)
。action终于出场啦!store.dispatch(getTodos({items:todoDemoList}))//给老大进贡
console.log(store.getState().todos[1])//有数据了
store.dispatch(toggleTodo({items:todoDemoList,id:1}))//修改某一个小罗罗
console.log(store.getState().todos[1])//修改为功
复制代码
subscribe(监视器listener)
看着你呢,小样给我注意点。不过此刻要注意,咱们要把监听器放在全部的dispatch
执行以前,否则就捕捉不到dispatch
了。要在一切还没发生以前,就准备好,否则就要给小样们钻空子了。就像盗窃同样,小偷已经偷完跑路了,你再装监控,也逮不住这个小偷啊。store.subscribe(()=>{
console.log(store.getState())//监控这手下的一举一动
})
复制代码
store.subscribe()
的返回值,这个返回值是一个方法,就像这样store.subscribe()()
let unsubscribe=store.subscribe(()=>{
console.log(store.getState())//监控这手下的一举一动
})
store.dispatch(toggleTodo({items:todoDemoList,id:1}))//老大在watching,当心翼翼。
unsubscribe()//放了大家,出去浪吧
store.dispatch(toggleTodo({items:todoDemoList,id:1}))//竟然真的没有再继续监视我了,放飞自我。
复制代码
combineReducers(小弟们)
一个帮派只能有一个老大!可是能够有颇有小弟,每一个小弟各司其职。可是要将这些小弟统一管理起来,这个时候就要用combineReducers
了。
用相同的方法建立一个filterAction
,而后用combineReducers
一下,接下来就能够愉快地合做了。
...
const filterAction = require('./reducers/filterAction')
const {showCompleted} = require('./actions/filterAction')
...
const rootReducer = combineReducers({todo: todo, filterAction: filterAction})
....
store.dispatch(showCompleted({items:todoDemoList}))//success执行啦!
复制代码