前端小库

dva model理解

2018-05-04  本文已影响362人  FConfidence
  1. 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 }
    },
  },

};
  1. 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);
  1. 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;
  1. 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": ""
      }
    }
  }
}
  1. 参考 https://juejin.im/entry/5852184b128fe1006b5454c6
    https://github.com/dvajs/dva/blob/master/README_zh-CN.md
上一篇下一篇

猜你喜欢

热点阅读