Redux基础
const Redux = require('redux'); const reducer = function(state, action) { if (action.type === 'changeName') { // const newState = JSON.parse(JSON.stringify(state));
// 不能直接修改原来的state对象 return Object.assign({}, state, {name: action.name}); } else { // 未配置情况,返回原来的state return state; } } // 参数: reducer(return state), [init state] const store = Redux.createStore(reducer, {name: 'init name', age: 20}); // 订阅监听 store.subscribe(() => console.log(store.getState())); // 同步dispatch const action = {
changeName() {
return { type: 'changeName', name: 'lily'
}
},
increment (number) {
return {
type: "increment",
data: number
}
}
}
store.dispatch(action);
redux中, Redux API主要有:
1. createStore()
2. applyMiddleware()
3. combineReducers()
// combineReducers 实现原理 // 将各个reducer函数包裹在一个对象中,最后通过生成一个新reducer函数 // function combineReducers(reducers) { // return function reducer(state, action) { // let newState = {}; // for (let key in reducers) { // 把state中每一个属性值作为state,带入对应的Reducer中进行处理 // newState[key] = reducers[key](state[key],action); // } // } // }
const Redux = require('redux'); // const state = { a: [], b: [], c:{ name: '', group: []} }; const aReducer = function(state, action) { if (typeof state === 'undefined') return []; switch (action.type) { case 'a': return state.concat([action.data]); default: return state; } } const bReducer = function(state, action) { if (typeof state === 'undefined') return []; switch (action.type) { case 'b': return state.concat([action.data]); default: return state; } } const cNameReducer = function(state, action) { if (typeof state == 'undefined') return ''; switch (action.type) { case 'c': return action.name; default: return state; } } const cGroupReducer = function(state, action) { // state对应的是group的value if (typeof state === 'undefined') return []; switch(action.type) { case 'c': return state.concat(action.item); default: return state; } } const cReducer = function (state, action) { // state对应的是c的value if (typeof state === 'undefined') return {name: '', group: []}; switch(action.type) { case 'c': // 返回reducer处理函数,然后调用 return Redux.combineReducers({name: cNameReducer, group: cGroupReducer})(state, action); default: return state; } } // 每个属性对应的reducer const reducers = Redux.combineReducers({a: aReducer, b: bReducer, c: cReducer}); const store = Redux.createStore(reducers, {a: [111], b: [222], c:{ name: 'hi', group:[] }}); store.subscribe(() => console.log(store.getState())); const action1 = { type: 'b', data: 'lead' }; const action2 = { type: 'a', data: 'tail' } const action3 = { type: 'c', name: 'jkp', item: 'pp' } store.dispatch(action1); store.dispatch(action2); store.dispatch(action3);
store API包括以下几个:
1. getState()
2. subscribe(callback)
3. dispatch(action)
Redux默认只支持同步action[返回对象](即:dispatch本身只能进行同步触发),若要实现异步action,需要借助一些特殊的插件,如redux-thunk,redux-promise。
let action = { // 同步action,返回一个对象 increment (number) { return { type: "increment", data: number } }, // 异步action, 返回一个函数 asyncIncrement (number) { return dispatch => { // 函数内部执行异步操作 setTimeout(() => { // dispatch一个同部的action对象 dispatch({ type: "increment", data: number }) }, 1000); } }, }
与此同时,在createStore()加入第二个参数--中间件 Redux.applyMiddleware(xxx)
const thunk = require("redux-thunk").default; const store = Redux.createStore(reducer, Redux.applyMiddleware(thunk));
这里提一下‘redux-thunk'这个中间件的使用[转自:https://juejin.im/post/6844903505199628301]
import { createStore, applyMiddleware } from 'redux'; import thunk from 'redux-thunk'; import rootReducer from './reducers/index'; //注册thunk到applyMiddleware const createStoreWithMiddleware = applyMiddleware( thunk )(createStore); const store = createStoreWithMiddleware(rootReducer); //action方法 function increment() { return { type: INCREMENT_COUNTER }; } //执行一个异步的dispatch function incrementAsync() { return dispatch => { setTimeout(() => { dispatch(increment()); }, 1000); }; }
源码分析
// thunk-redux 源码 function createThunkMiddleware(extraArgument) { // 将dispatch和getState传入action,next()和action()是redux提供的方法。 return ({ dispatch, getState }) => next => action => { // 接着做判断,如果action是一个function,就返回action(dispatch, getState, extraArgument),否则返回next(action) if (typeof action === 'function') { return action(dispatch, getState, extraArgument); } return next(action); }; }
const thunk = createThunkMiddleware(); // 给thunk设置一个属性withExtraArgument,并且将createThunkMiddleware整个函数赋给它。 thunk.withExtraArgument = createThunkMiddleware; export default thunk;
总结:thunk是一个中间函数,它的返回值是一个函数表达式。action里面可能传递多个参数,我们不可能再专门替每个action写一个传递方法。那么就有了thunk的出现,thunk可以将多个参数的函数作为一个参数传递。
例如有这样一个action
function test(arg1, arg2, ...) { return { type: "TEST", arg1, arg2, ... } }
然后我们在执行dispatch()方法是,需要把test()的返回值作为参数传递。这样就解决了多参数传递的问题,这个test()就成了一个thunk。
promise实现异步触发
// 借助promise实现异步触发 function callAction() { const actionPromise = new Promise((resovle, reject) => { const action = { type: 'changeName', name: 'lily' }; resovle(action); }) actionPromise.then((action) => { store.dispatch(action); }) } callAction();
PS: redux-devtools下载安装 https://github.com/zalmoxisus/redux-devtools-extension/releases
然后在项目目录下npm i redux-devtools-extension --save-dev
import {composeWithDevTools} from 'redux-devtools-extension';
const store = Redux.createStore(reducer, composeWithDevTools(Redux.applyMiddleware(thunk)));