why redux?
- 随着 JavaScript 单页应用开发日趋复杂,管理不断变化的 state 非常困难
- Redux的出现就是为了解决state里的数据问题
- 在React中,数据在组件中是单向流动的
- 数据从一个方向父组件流向子组件(通过props),由于这个特征,两个非父子关系的组件(或者称作兄弟组件)之间的通信比较麻烦
what is redux?
工作流
设计思想
- Redux是将整个应用状态存储到到一个地方,称为store
- store里面保存一棵状态树(state tree)
- 组件可以派发(dispatch)行为(action)给store,而不是直接通知其它组件
- 其它组件可以通过订阅store中的状态(state)来刷新自己的视图.
三大原则
- 整个应用的 state 被储存在一棵 object tree 中,并且这个 object tree 只存在于唯一一个 store 中 State 是只读的,惟一改变 state 的方法就是触发 action,
- action是一个用于描述已发生事件的普通对象 使用纯函数来执行修改,为了描述action如何改变state tree ,你需要编写 reducers
- 单一数据源的设计让React的组件之间的通信更加方便,同时也便于状态的统一管理
how redux?
1.安装
npm i redux -S
2.简单例子
1.引入
import {createStore} from 'redux';
//createStore 用来创建状态仓库
2.创建state
let initState = {
title: 'star'
}
3.创建reducer
const CHANGETITLE = 'CHANGETITLE'; //action-todos
function reducer(state= initState, action){
switch(action.type){
case CHANGETITLE:
return state.title = action.title;
}
}
4.创建仓库
let store = createStore(reducer);
5.触发dispatch中传入action
store.dispatch({type: CHANGETITLE, title: 'xingxing'})
完整代码
import {createStore} from 'redux';
const CHANGETITLE = 'CHANGETITLE';
function reducer(state= initState, action){
switch(action.type){
case CHANGETITLE:
state.title = action.title;
}
console.log(state);
}
let store = createStore(reducer);
store.subscribe(()=>{ //订阅事件,在dispatch时触发
console.log('render');
})
store.dispatch({type: CHANGETITLE, title: 'xingxing'})
复杂些例子
在真实开发中需要开辟一个文件空间来管理仓库
- 文件结构化
- 多reducer,合并reducer
1.actions
action-type.js
//action-type衡量,通过引入使用,减少拼写错误引发的问题
export const INCREMENT = 'INCREMENT'
export const DECREMNET = 'DECREMNET'
actions/count.js
import * as types from "../action-types"
//用于生成action
let counter = {
add(n){
return {type: types.INCREMENT, count: n}
}
}
export default counter
2.reducers
reducers/count.js
import {INCREMENT,DECREMENT} from '../actions/action-type'
let initState = {
count: 0
}
function reducer(state = initState,action){
switch(action.type){
case INCREMENT:
state.count = state.count + action.number;
break;
case DECREMENT:
state.count = state.count - action.number;
break;
}
return state
}
export default reducer
合并reducer
reducers/index.js
import todos from './todo';
import count from './count';
import {combineReducers} from 'redux'
let reducers = combineReducers({
todos,
count
})
export default reducers;
store/index.js 初始化仓库
import {INCEMENT,DECREMENT} from './actions/action-type';
import {createStore} from 'redux';
import reducers from './reducers'
export default createStore(reducers);
how is redux work?
- redux的数据源是创建reducer时,传进去的initState。
- 为了避免state被随意篡改,redux通过dispatch reducer来更改数据。
- redux可以通过subscribe订阅状态修改事件
//简单实现
function createStore(reducer){
let state;
let listeners = [];
function subscribe(listener){
listeners.push(listener);
return ()=> listeners = listeners.filter(fn=>fn!==listener);
}
function dispatch(action){
listeners.forEach(listener=>listener());
reducer(state, action)
}
dispatch({})
function getState(){
return state;
}
return {subscribe, dispatch, getState}
}
合并reducer
function combineReducers(reducers){
return (state={},action)=>{
let newState = {};
for(let key in reducers){
let s = reducers[key](state[key],action);
newState[key] = s;
}
return newState;
}
}
完整代码
function createStore(reducer){
let state;
let listeners = [];
function subscribe(listener){
listeners.push(listener);
return ()=>{
listeners = listeners.filter(l=> l!==listener)
}
}
dispatch({})
function dispatch(action){
state = reducer(state,action);
listeners.forEach(l=>l());
}
function getState(){
return state;
}
return {subscribe,dispatch,getState};
}
function combineReducers(reducers){
return (state={},action)=>{
let newState = {};
for(let key in reducers){
let s = reducers[key](state[key],action);
newState[key] = s;
}
return newState;
}
}
export {createStore,combineReducers}
最近在研究redux,欢迎指出问题。后续更新react-redux全家桶系列研究