- example.js
import key from 'keymaster';
export default {
namespace: 'example',
state: {
count: 0,
test: 'just have a test'
},
// Subscriptions 是一种从 源 获取数据的方法,它来自于 elm。
// 用于订阅一个数据源,然后根据条件 dispatch 需要的 action。
subscriptions: {
setup({ dispatch, history }) { // eslint-disable-line
console.log('setup addEventListener')
},
keyEvent({dispatch, history}) {
console.log('ctrl+up addEventListener')
key('⌘+up, ctrl+up', () => { dispatch({type:'save', payload: 0, testStr: 'keyup Enter'}) });
},
},
// Effect 被称为副作用,在我们的应用中,最常见的就是异步操作,Effects 的最终流向是通过 Reducers 改变 State。
// 核心需要关注下 put, call, select。
effects: {
* fetch({ payload }, { call, put, select }) { // eslint-disable-line
console.log('*fetch test')
yield put({ type: 'save', payload }); // 用户触发action 不带namespace表明是本model中的方法
/*
const todos = yield select(state => state.todos); // 这边的 state 来源于全局的 state
select 方法提供获取全局 state 的能力,
也就是说,在这边如果你有需要其他 model 的数据,则完全可以通过 state.modelName 来获取
yield call(addTodo, todo); // 用于调用异步逻辑,支持 promise 。
yield put({ type: 'add', payload: todo }); // 用于触发 action 。
这边需要注意的是,action 所调用的 reducer 或 effects 来源于本 model 那么在 type 中不需要声明命名空间,
如果需要触发其他非本 model 的方法,则需要在 type 中声明命名空间,如 yield put({ type: 'namespace/fuc', payload: xxx });
*/
},
},
reducers: {
// action行为 返回新的数据对象 在其他组件中通过 props.dispatch('namespace/add', {}) 来进行调用
save(state, action) {
console.log('save: action: ', action.payload)
// console.log( { ...state, ...action.payload })
return Object.assign({}, state, {count: action.payload, test: action.testStr?action.testStr:'just have a async test'});
},
add(state, action) {
console.log(action.type, '+1')
return { count: state.count + 1, test: state.test }
},
minus(state, action) {
console.log(action.type, '-' + action.payload)
return { count: state.count - action.payload, test: state.test }
},
},
};
- IndexPage.js
import React from 'react';
import { connect } from 'dva';
import styles from './IndexPage.css';
import MainLayout from '../components/MainLayout/MainLayout';
function IndexPage(props) {
return (
<MainLayout location={props.location}>
<div className={styles.normal}>
{JSON.stringify(props.example)}
<button key="add" onClick={() => { props.dispatch({type: 'example/add'})}}>+1</button>
<button key="minus" onClick={() => { props.dispatch({type: 'example/minus', payload: 2})}}>-2</button>
<br/>
<button key="fetch" onClick={() => { props.dispatch({type: 'example/fetch', payload: 100})}}> 异步effect</button>
<h1 className={styles.title}>Yay! Welcome to dva!</h1>
<div className={styles.welcome} />
<ul className={styles.list}>
<li>To get started, edit <code>src/index.js</code> and save to reload.</li>
<li><a href="https://github.com/dvajs/dva-docs/blob/master/v1/en-us/getting-started.md">Getting Started</a></li>
</ul>
</div>
</MainLayout>
);
}
IndexPage.propTypes = {
};
// 从store中example
export default connect( ({example})=> ({example}) )(IndexPage);
- router.js
import React from 'react';
import { Router, Route, Switch } from 'dva/router';
// import IndexPage from './routes/IndexPage';
// 异步模块加载
import dynamic from 'dva/dynamic'
function RouterConfig({ history, app }) {
const IndexPage = dynamic({
app,
component: () => import('./routes/IndexPage'),
});
const UsersPage = dynamic({
app,
models: () => [
import('./models/users'),
],
component: () => import('./routes/UsersPage'),
});
return (
<Router history={history}>
<Switch>
<Route path="/" exact component={IndexPage} />
<Route exact path="/users" component={UsersPage} />
</Switch>
</Router>
);
}
export default RouterConfig;
- scr/index.js
import dva from 'dva';
import './index.css';
import { browserHistory } from 'dva/router';
import createLoading from 'dva-loading';
import { message } from 'antd';
const ERROR_MSG_DURATION = 3; // 3 秒
// ##dva五部曲
// 1. Initialize
const app = dva({
history: browserHistory,
onError(e) {
message.error(e.message, ERROR_MSG_DURATION);
},
});
// 2. Plugins 插件的使用 为可选项
// app.use({});
app.use(createLoading());
// 3. Model 注册 注册到store上
app.model(require('./models/example').default);
/*
也可以使用这种方法注册model
app.model({
namespace: 'todos', //model 的 namespace
state: [], // model 的初始化数据
reducers: {
// add 方法就是 reducer,可以看到它其实非常简单就是把老的 state 和接收到的数据处理下,返回新的 state
add(state, { payload: todo }) {
return state.concat(todo);
},
},
};
*/
// 4. Router 配置 Router
app.router(require('./router').default);
// 5. Start
app.start('#root');
5 .webpackrc
{
"proxy":
{
"/api":
{
"target": "http://localhost:3000/",
"changeOrigin": true,
"pathRewrite":
{
"^/api": ""
}
}
}
}
网友评论