初识React(9):dva简介

媒介

dva 首先是一个基于 redux 和 redux-saga 的数据流计划,然后为了简化开辟体验,dva 还分外内置了 react-router 和 fetch,所以也能够理解为一个轻量级的运用框架。
dva官网地点:https://dvajs.com/

import dva from 'dva';

// 1. Initialize
const app = dva();

// 2. Plugins
app.use({});

// 3. Model
app.model(require('./models/example').default);

// 4. Router
app.router(require('./router').default);

// 5. Start
app.start('#root');

dva唯一6个api,以下引见:

1. const app = dva(options)

建立运用,返回dva实例

options中包括:

(1) history:默以为hashHistory,假如要设置history为browserHistory,则

import createHistory from 'history/createBrowserHistory';
const app = dva({
  history: createHistory(),
});

(2) initialState: 指定初始数据,优先级高于model中的state,默以为{}

(3) onError: 治理全局失足状况,以下:

const app = dva({
  onError(e){
    console.log(e);
  }
});

(4) onAction(fn | fn[]): 在action被dispatch时触发,用于注册redux中间件,支撑函数花样或许函数数组花样,以下经由过程redux-logger准许日记,如:

import createLogger from 'redux-logger';
const app = dva({
  onAction: createLogger(opts),
});

(5) onStateChange(fn): state转变时触发,可用于同步state 到 localStorage,服务器端等

(6) onReducer(fn): 封装 reducer 实行。比方借助 redux-undo 完成 redo/undo :

import undoable from 'redux-undo';
const app = dva({
  onReducer: reducer => {
    return (state, action) => {
      const undoOpts = {};
      const newState = undoable(reducer, undoOpts)(state, action);
      // 因为 dva 同步了 routing 数据,所以须要把这部份复原
      return { ...newState, routing: newState.present.routing };
    },
  },
});

(7) onEffect(fn): 封装 effect 实行。比方 dva-loading 基于此完成了自动处置惩罚 loading 状况。

(8) onHmr(fn): 热替代相干,现在用于 babel-plugin-dva-hmr

(9) extraReducers: 指定分外的 reducer,比方 redux-form 须要指定分外的 form reducer

import { reducer as formReducer } from 'redux-form'
const app = dva({
  extraReducers: {
    form: formReducer,
  },
});

(10) extraEnhancers: 指定分外的 StoreEnhancer ,比方连系 redux-persist 的运用

import { persistStore, autoRehydrate } from 'redux-persist';
const app = dva({
  extraEnhancers: [autoRehydrate()],
});
persistStore(app._store);

2.app.use(hooks)

设置 hooks 或许注册插件。(插件终究返回的是 hooks )

比方注册 dva-loading 插件的例子:

import createLoading from 'dva-loading';
...
app.use(createLoading(opts));

hooks 包括2中(3)到(10)

3.app.model(model)

注册model

model 是 dva 中最主要的观点,以下是典范的例子:

app.model({
  namespace: 'todo',
  state: [],
  reducers: {
    add(state, { payload: todo }) {
      // 保留数据到 state
      return [...state, todo];
    },
  },
  effects: {
    *save({ payload: todo }, { put, call }) {
      // 挪用 saveTodoToServer,胜利后触发 `add` action 保留到 state
      yield call(saveTodoToServer, todo);
      yield put({ type: 'add', payload: todo });
    },
  },
  subscriptions: {
    setup({ history, dispatch }) {
      // 监听 history 变化,当进入 `/` 时触发 `load` action
      return history.listen(({ pathname }) => {
        if (pathname === '/') {
          dispatch({ type: 'load' });
        }
      });
    },
  },
});

model 包括 5 个属性:

namespace: model 的定名空间,同时也是他在全局 state 上的属性,只能用字符串,不支撑经由过程 . 的体式格局建立多层定名空间。

state: 初始值,优先级低于传给 dva() 的 opts.initialState,以下:

const app = dva({
  initialState: { count: 1 },
});
app.model({
  namespace: 'count',
  state: 0,
});

此时,在 app.start() 后 state.count 为 1

reducers: 以 key/value 花样定义 reducer。用于处置惩罚同步操作,唯一能够修正 state 的处所。由 action 触发,花样为 (state, action) => newState 或 [(state, action) => newState, enhancer]

effects: 以 key/value 花样定义 effect。用于处置惩罚异步操作和营业逻辑,不直接修正 state。由 action 触发,能够触发 action,能够和服务器交互,能够猎取全局 state 的数据等等。花样为

*(action, effects) => void 或 [*(action, effects) => void, { type }]。

subscriptions: 以 key/value 花样定义 subscription。subscription 是定阅,用于定阅一个数据源,然后根据须要 dispatch 响应的 action。在 app.start() 时被实行,数据源能够是当前的时候、服务器的 websocket 衔接、keyboard 输入、geolocation 变化、history 路由变化等等。花样为 ({ dispatch, history }, done) => unlistenFunction。注重:假如要运用 app.unmodel(),subscription 必需返回 unlisten 要领,用于作废数据定阅。

4.app.unmodel(namespace)

作废 model 注册,清算 reducers, effects 和 subscriptions。subscription 假如没有返回 unlisten 函数,运用 app.unmodel 会赋予正告

5.app.router(({ history, app }) => RouterConfig)

注册路由表。通常是如许的:

import { Router, Route } from 'dva/router';
app.router(({ history }) => {
  return (
    <Router history={history}>
      <Route path="/" component={App} />
    <Router>
  );
});

引荐把路由信息抽成一个零丁的文件,如许连系 babel-plugin-dva-hmr 可完成路由和组件的热加载,比方:

app.router(require('./router'));

而有些场景能够不运用路由,比方多页运用,所以也能够传入返回 JSX 元素的函数。比方:

app.router(() => <App />);

6.app.start(selector)

启动运用。selector 可选,假如没有 selector 参数,会返回一个返回 JSX 元素的函数。

app.start('#root');

那末什么时候不加 selector?罕见场景有测试、node 端、react-native 和 i18n 国际化支撑。

比方经由过程 react-intl 支撑国际化的例子:

import { IntlProvider } from 'react-intl';
...
const App = app.start();
ReactDOM.render(<IntlProvider><App /></IntlProvider>, htmlElement);

本文参考官网:https://dvajs.com/api/#dva-api

    原文作者:hope93
    原文地址: https://segmentfault.com/a/1190000017416070
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞