app.js是首页面,路由放此。
sagas在此页面被引用。
import rootSaga from './sagas'
const store = configureStore(initialState)
store.runSaga(rootSaga);
1)FL.js
修改对应的接口Path值,便于后期对接口地址的管理。
SupSearch:'/api/Order/supSearch.json',
SupState:'/api/Order/supState.json',
2)sagas
中间件,只会在应用启动时调用(但初始启动的sagas可能会动态的调用其它sagas),用于监听发起的action,然后决定这个action用来做什么。
如:1.发起一个异步调用(ajax请求) 2.发起其它的action到store。 3.调用其它的sagas
index.js里面放所有的sagas。
import { watchGetAccountSaga } from './account' import {supSearch} from './supSearch' export default function* rootSaga() { yield [ // 更多 watchGetAccountSaga(), supSearch(), ] }
子saga:有两个Generator函数。其中一个通过while(true),take方法来一直监听action。
只有当此事件被dispatch则fork第二个Generator函数。(此步骤避免了同时发起多个不必要的请求。
只有当view页面componentWillMount 才触发此action,发起请求。)
componentWillMount(){ this.props.initialDispatch() },
import { SUPSEARCHACTION, supSearchSucceed,supSearchFailed} from '../actions/sup' export function* supSearch() { while (true) { yield take(SUPSEARCHACTION) yield fork(fetchSupSearchApi) } }
第二个Generator方法主要用来生成fetch请求。
任务要被beginTask和endTask包裹。在请求成功之后,将请求到的数据dispatch一个对应的action(成功:supSearchSucceed(res) ) 失败(supSearchFailed(e) )。
function* fetchSupSearchApi(){ try { yield put( beginTask() ) const response = yield call(fetch, FL.PATH.API.SupSearch) const res = yield response.json() if (!res) { return false } else { yield put( supSearchSucceed(res) ) (成功) } } catch (e) { yield put( supSearchFailed(e) ) (失败) } finally { yield put( endTask() ) } }
mockjs也是放在此文件中。
// mock 代码放在 __DEBUG__ 代码块内,生产环境会删除代码块
if (__DEBUG__) { let data = Mock.mock({ 'Status': '200', 'Position': '001', 'ErrorCode': '001', 'Data|1-10': [{ 'productNumber': /[A-Z][A-Z]d{3}[a-z]d{3}/, 'productName': '@ctitle(3, 5)', 'supplierName': '@ctitle(3)', 'productStockStatus|1-100': 1, 'faceValue|1-1000': 1, 'productPrice|1-100': 1, 'type|1-4': 1, 'averageChargeTime':'@natural(0,200)'+'min', 'complaintRate':'@natural(0,100)'+'%', 'successRate': '@natural(0,100)'+'%', 'today|1-100': 1, 'week|1-1000':1 , 'month|1-10000': 1, 'purchaseApplyStatus': '@boolean()' }] }); fetchMock.mock(FL.PATH.API.SupSearch, data); // fetchMock.mock(FL.PATH.API.ACCOUNT, 404); }
3)action
在对应的action文件sup.js中,
export const SUPSEARCHACTION = 'SUPSEARCHACTION' export const SUPSEARCH_SUCCEED = 'SUPSEARCH_SUCCEED' export const SUPSEARCH_FAILED = 'SUPSEARCH_FAILED'
分别对应触发,请求成功、请求失败的action:
export function supSearchAction(){ return { type:SUPSEARCHACTION } } export function supSearchSucceed(items){ return { type:SUPSEARCH_SUCCEED, items } } export function supSearchFailed(error) { return { type: SUPSEARCH_FAILED, error, } }
4)reducer
index.js中为总reducer。通过import将各个reducer引入进来,通过combineReducer将各个子reducer结合起来。configureStore.js中引入此rootReducer。
import supSearch from './supSearch' import supState from './supState' const rootReducer = combineReducers({ routing: routerReducer, supSearch, supState, }) export default rootReducer
将action的三种type值引入,触发不同的type值会有不同的处理。
1、当触发SUPSEARCHACTION时,将isfetching设为true,代表开始请求数据。
2、当触发SUPSEARCH_SUCCEED时,将isfetching设为false,代表请求完成,成功,并将请求到的参数返回给items,items的值同步到state当中。
3、当触发SUPSEARCH_FAILED时,将isfetching设为false,代表请求完成,失败。返回错误。
import {SUPSEARCHACTION,SUPSEARCH_SUCCEED,SUPSEARCH_FAILED} from '../actions/sup' export default function supSearch (state = {}, action) { switch (action.type) { case SUPSEARCHACTION: return { ...state, isfetching:true, } case SUPSEARCH_SUCCEED: return { ...state, isfetch:false, items: action.items, } case SUPSEARCH_FAILED: return { ...state, isfetching: false, error: action.error, }; default: return state } }
5)containers
用于将state进行处理,处理好的数据通过connect传递给component中的view页面 涉及到reselect(创建选择器)。
import { connect} from 'react-redux' import SupSearch from '../components/SupSearch/js/SupSearch' import {supSearchAction} from '../actions/sup' import {createSelector } from 'reselect' const defaultValue = []; const stateItemSelector = (state) =>state.supSearch.items || defaultValue const stateSelector = createSelector ( [stateItemSelector], (stateItem) => { return stateItem } ) const mapStateToProps = (state) =>{ return { items:stateSelector(state), } } const mapDispatchToProps = (dispatch) =>{ return { initialDispatch(){ dispatch(supSearchAction()) }, } } export default connect( mapStateToProps, mapDispatchToProps )(SupSearch)
6)component
此部分即为view模块。只有当组件即将被渲染时,才发起action,触发saga部分的yield take(SUPSEARCHACTION)
initialDispatch方法即为5)中mapDispatchToProps传过来的方法。
componentWillMount(){ this.props.initialDispatch() },