目錄回顧react
startup
,cc也提供configure
來配置模塊相關信息哦^_^startup
時將模塊的store
、reducer
、computed
、init
一次性配置好login
、product
,以及重寫cc的內置模塊$$global
login
模塊相關代碼// code in models/login/index.js
import reducer from './reducer';
import state from './state';
import init from './init';
export default {reducer, state, init}
複製代碼
// code in models/login/state.js
export default {
loading:false,
onlineCount:0,
failReason:'',
uid:0,
username:'',
role:'',
}
複製代碼
// code in models/login/reducer.js
import api from 'service/user';
function changeLoading(loading){
return {loading}
}
async function loginWithPassword({payload:{username,password}, dispatch}){
await dispatch('login/changeLoading', true);
// 等價於寫 await dispatch({module:'login', type:'changeLoading', payload:true});
// 備註,若是這裏肯定來來自於login模塊的組件實例調用的this.$$dispatch('updatePassword',{uid,password})
// 這裏還能夠簡寫爲dispatch('changeLoading', true),由於此dispatch句柄默認是去改變的模塊就是觸發該updatePassword函數的$$dispatch調用實例所屬的模塊
const {success, message, data} = await api.loginWithPassword(username,password);
if(success){
const {uid, username, role, customizedBorderColor} = data;
//派發到$$global模塊修改相應的狀態
dispatch('$$global/changeBorderColor', customizedBorderColor);
return {loading:false, uid, username, role};
}else return {loading:false, failReason:message};
}
async function updatePassword({payload:{uid,password}, dispatch}){
await dispatch('login/changeLoading', true);
const {success, message, data} = await api.updatePassword(uid,password);
if(success) return {loading:true};
else return {loading:false, failReason:message};
}
export default {
changeLoading,
loginWithPassword,
updatePassword,
}
複製代碼
//code in models/login/init.js
import api from 'service/userApi';
export default setState=>{
api.getOnlineCount().then(onlineCount=>{
setState({onlineCount});
});
}
複製代碼
product
模塊相關代碼// code in models/product/index.js
import reducer from './reducer';
import state from './state';
export default {reducer, state}
複製代碼
// code in models/product/state.js
export default {
loading:false,
pageSize:10,
currentPage:0,
totalPage:0,
totalCount:0,
productList:[],
}
複製代碼
// code in models/product/reducer.js
import api from 'service/product';
import cc from 'react-control-center';
function changeLoading(loading){
return {loading}
}
async function _fetchProduct(currentPage, pageSize){
const {list:productList, totalCount} = await api.fetchProduct(currentPage, pageSize);
const totalPage = Math.ceil(totalCount/pageSize);
return {productList, totalCount, totalPage};
}
async function nextPage({dispatch, moduleState}){
await dispatch('changeLoading', true);
const {currentPage, pageSize} = moduleState;
const nextPage = currentPage+1;
const {productList, totalCount, totalPage} = await _fetchProduct(nextPage, pageSize);
return {loading:false, productList, totalCount, totalPage, currentPage:nextPage};
}
async function prevPage({dispatch, moduleState}){
await dispatch('changeLoading', true);
const {currentPage, pageSize} = moduleState;
const nextPage = currentPage-1;
const {productList, totalCount, totalPage} = await _fetchProduct(nextPage, pageSize);
return {loading:false, productList, totalCount, totalPage, currentPage:nextPage};
}
async function changePageSize({dispatch, moduleState, payload:pageSize}){
await dispatch('changeLoading', true);
const {currentPage} = moduleState;
const {productList, totalCount, totalPage} = await _fetchProduct(currentPage, pageSize);
return {loading:false, productList, totalCount, totalPage, pageSize};
}
async function refreshCurrentPage({dispatch, moduleState}){
await dispatch('changeLoading', true);
const {currentPage, pageSize} = moduleState;
const {productList, totalCount, totalPage} = await _fetchProduct(currentPage, pageSize);
return {loading:false, productList, totalCount, totalPage};
}
//上傳統計用戶的刷新行爲,由於該函數不返回任何新的state,將不觸發cc組件實例的渲染
function uploadRefreshBehavior(){
const loginModuleState = cc.getState('login');
const {uid} = loginModuleState
api.uploadRefreshBehavior({uid, action:'refreshCurrentPage'});
}
//cc並不強制要求每個reducer函數都返回一個新的片段state,該方法經過dispatch組合了另外兩個reducer函數
function refreshCurrentPageAndTrack({dispatch}){
dispatch('refreshCurrentPage');
dispatch('uploadRefreshBehavior');
}
export default {
changeLoading,
nextPage,
prevPage,
changePageSize,
refreshCurrentPage,
uploadRefreshBehavior,
refreshCurrentPageAndTrack,
}
複製代碼
$$global
模塊相關代碼// code in models/global/index.js
import reducer from './reducer';
import state from './state';
import computed from './computed';
export default {reducer, state, computed}
複製代碼
// code in models/global/state.js
export default {
customizedBorderColor:'#FFFFFF',
}
複製代碼
// code in models/global/reducer.js
function changeBorderColor({payload:customizedBorderColor}){
return {customizedBorderColor};
}
複製代碼
//code in models/global/computed.js
export default {
customizedBorderColor(customizedBorderColor){
return `1px solid ${customizedBorderColor}`;
}
}
複製代碼
StartUpOption
裏// code in startup-cc.js
import loginModel from 'models/login';
import productModel from 'models/product';
import globalModel from 'models/global';
import cc from 'react-control-center';
function myMiddle1(executionCotext, next){
console.log(executionCotext);
// here write your code
next();
}
function myMiddle2(executionCotext, next){
console.log(executionCotext);
// here write your code
next();
}
const models = [
{module:'login',model:loginModel},
{module:'product',model:productModel},
{module:'$$global',model:globalModel},
];
const store={}, reducer={}, init={}, computed={};
models.forEach(item=>{
const {module, model:{state, reducer:_reducer, init:_init, computed:_computed}} = item;
if(state)store[module]=state;
if(_reducer)reducer[module]=_reducer;
if(_init)init[module]=_init;
if(_computed)computed[module]=_computed;
});
cc.startup({
isModuleMode:true,
store,
reducer,
init,
computed,
// 注意,此處配置了中間件函數,任何cc實例觸發了改變state的行爲,
// cc都會前調用中間件函數鏈而後纔開始改變state, 爲第三方編寫插件預留了可操做入口,例如計劃中的rcc-state-changging-logger
middlewares:[myMiddle1, myMiddle2]
});
複製代碼
// code in startup-cc.js
import cc from 'react-control-center';
function myMiddle1(executionCotext, next){
console.log(executionCotext);
// here write your code
next();
}
function myMiddle2(executionCotext, next){
console.log(executionCotext);
// here write your code
next();
}
cc.startup({
isModuleMode:true,
middlewares:[myMiddle1, myMiddle2]
});
複製代碼
// code in configure-cc.js
import loginModel from 'models/login';
import productModel from 'models/product';
import globalModel from 'models/global';
import cc from 'react-control-center';
const models = [
{module:'login',model:loginModel},
{module:'product',model:productModel},
{module:'$$global',model:globalModel},
];
const store={}, reducer={}, init={}, computed={};
models.forEach(item=>{
const {module, model:{state, reducer:_reducer, init:_init, computed:_computed}} = item;
const option = {};
if(_reducer)option.moduleReducer = _reducer;
if(_init)option.init=_init;
if(_computed)option.computed=_computed;
cc.configure(module, state, option);
});
複製代碼
//code in App.js
import 'startup-cc.js';//注意此處必定是先引入startup-cc.js
import 'configure-cc.js';
複製代碼
cc.configure
一樣也能夠不須要在一處文件裏集中式的調用,這樣方便用戶按照本身的習慣和理解來組織代碼|________components
| |________Login
| | |________model
| | | |________state.js
| | | |________reducer.js
| | | |________init.js
| | | |________index.js
| | |________index.js
複製代碼
components/Login/model/index.js
裏負責完成cc.configure
的調用import moduleReducer from './reducer';
import state from './state';
import init from './init';
import cc from 'react-control-center';
cc.configure('login', state, {moduleReducer, init});
複製代碼
components/Login/index.js
裏引用components/Login/model
,觸發cc動態加載login模塊// code in components/Login/index.js
import React from 'react';
import cc from 'react-control-center';
import './model';
@cc.register('Login',{module:'login', sharedStateKeys:'*'});
export default class Login extends React.Component{
//......
}
複製代碼
state
、init
、computed
等屬性配置在StartUpOption
裏