Redux里的倔强划定规矩与设想不少,大部分都邑与FP(函数式递次开辟)、革新底本的Flux架构设想有关。Redux官网文档上的三大基本原则,重要是由于有能够怕初学者不明白Redux中的一些限定或设想,所以先写出来申明,这内里也申清楚明了Redux的设想道理基本是怎样,所以强烈建议一切的初学者一定要彻底地明白这三大原则中的意义,多看几遍,对往后的进修会很有协助。以下离别申明,重要以原文的题目与内容申明,尽能够申明的比较清楚些。
单一原形泉源
你的全部运用中的state(状况),会存储在单一个store(存储)当中的一个对象树状构造里。
Redux中只要效单一个对象大树构造来的存储全部运用的状况,也就是全部运用中会用到的数据,称之为store
(存储)。但要注重的是store
(存储)并非只要纯真的数据罢了。store
就是运用递次范畴的状况,它是范例MVC中的Model(模子的)设想的观点,这设想是由Flux架构而来的,在底本的Flux架构中是许可多个store
的构造,Redux简化为只要单一个。
Redux的单一个store的设想有一些优点,对开辟者来讲,它能够轻易调试与视察状况的变化,状况存储于对象树状构造中,也很轻易作到重作/回复(Undo/Redo)的功用。由于只要一个store
,但假如store
里要储放多个差别的状况对象,以及每次的更动数据,天然就会变成了对象树状构造(object tree)。
另外,假如你想要从store中掏出现在的状况数据,能够用store的getState()
要领。
状况是唯读的
唯一能更动状况的是发送一个
action
(行动),action
是一个形貌”发作了什么事”的纯对象
这里指的”状况”,是上面说的储放在store中的状况数据,你”不能直接”对个中的状况数据更动,只能”间接”地作这事。这与本来的React中的state
与setState
的观点有点像,Redux的意义是你不能直接更动store
内里所纪录的状况值,只能”间接”地透过发送action
对象来叫store
更动状况。”间接”地更动状况是一个很症结的设想,这是Flux中单向数据流的重点之一,这关于每一个行动发作,最终会影响到什么状况上的更动,一个接一个的递次等等的一种严厉的设想。
你能够会以为”状况既然是唯读”,直接与间接有什么差别,”唯读”不就代表完整不能更动,这语句是否是有误?
“唯读”固然就是完整不能更动的意义没错,所以状况对象的更动是并非在本来的状况对象上更改它,而是由本来状况对象由于行动的到场后,发生一个全新的状况对象,用这全新的状况对象来庖代本来的状况对象罢了。这在实在天下中也许很难拿比方来申明,但在软体天下中这很能够很轻易杀青。
“发作了什么事”这句,是代表每一个action
都邑有一个type(范例),代表这个行动是要作什么用的,或是现在是发作了什么,比方是要新建一笔什么数据,或是删除全部数据等等,行动对象除了要申明它是要作什么以外,也须要包括所影响的数据。
发送一个action(行动),运用的是store.dispatch(action)
语法款式,下面这个例子就是一个要更动状况的代码:
store.dispatch({
type: 'COMPLETE_TODO',
index: 1
})
中心的谁人纯对象,就叫作action
(行动),它是一个纯真用于形貌发作了什么事与相干数据的纯对象:
{
type: 'COMPLETE_TODO',
index: 1
}
还记得我们在React中的state
与setState
要领的设想吗?state
也是不能直接更动的,一定要透过setState
要领才更动它。那这是为什么呢?由于setState
不光只是更动state
值,它还要作从新衬着的行动,React须要比对现在的状况,与即将要更改的状况,如许才进挪动新衬着的事情。Redux的设想中store
是与React中的state
比拟,它们之间有一些相似的设想。
更动只能由纯函数来举行
要指导状况树要怎样依actions(行动)来作转变,你须要撰写地道的归结函数(reducers)
Redux中的reducer的原型会长得像下面如许,你能够把它看成就是 之前的状况 + 行动 = 新的状况
的公式:
(previousState, action) => newState
注: 你能够参考Redux中Reducers这一章的内容,内里有实例。
不过,Redux中的reducer一定是纯函数(pure function),也就是不能有副作用的函数。因而由reducer所发生的新状况,并非直接修正之前的状况而来,而是一个复制之前状况,然后加上行动转变的部分,发生的一个新的对象,它如许设想是有缘由的。
Redux的store设想,并非底本Flux架构中的store,而是ReduceStore,这个ReduceStore是一个在Flux中的store
进化版本,在申明中它有一个叫作reduce的要领,申明以下:
reduce(state: T, action: Object): T 归结(Reduces)现在的state(状况)与一个action(行动)到新的store中的state(状况)。一切的子类都须要实作这个要领。这个要领必需是地道而是无副作用。
那为什么要用这个进化的ReduceStore?它最后有申明一段:
不须要发送更动事宜注重一切继续自ReduceStore的store,不须要手动发送在reduce()中的更动事宜…state(状况)会自动地比对在每一个dispatch(发送)之前与以后,与自动地作发送更动事宜…
ReduceStore
的设想与Redux最一开始的版本差不多是同时间宣布的,在开辟者之间相互有交换。Redux的store运用了相似于ReduceStore的设想,所以要更动Redux中的store,须要透过reducer,这是为了简化底本在Flux数据流的实作流程。
reducer在Redux中扮演了十分重要的症结角色,它是一种对store中所寄存的状况,要怎样因应差别的行动而举行革新的函数,而store也是由reducer所建立,比方像下面的代码:
// @Reducer
//
// action payload = action.text
// 运用地道函数的数组unshift,不能有副作用
// state(状况)一开始的值是空数组`state=[]`
function todoApp(state = [], action) {
switch (action.type) {
case 'ADD_ITEM':
return [action.text, ...state]
default:
return state
}
}
// @Store
//
// 由reducer建立store
const store = createStore(todoApp)
针对运用中差别功用的状况,能够离别写出差别的reducer,Redux中供应了combineReducers
函数能够兼并多个reducer,比方以下的代码:
function todos(state = [], action) {
switch (action.type) {
case 'ADD_TODO':
return state.concat([ action.text ])
default:
return state
}
}
function counter(state = 0, action) {
switch (action.type) {
case 'INCREMENT':
return state + 1
case 'DECREMENT':
return state - 1
default:
return state
}
}
// rootReducer是个组合过的函数,
// 这里用的是对象属性初始设置简写法,
// combineReducers传参是一个对象
const rootReducer = combineReducers({
todos,
counter
})