react前端框架dva(三)

简介:

API

输出文件

dva

默认输出文件。

dva/router

默认输出 react-router 接口, react-router-redux 的接口通过属性 routerRedux 输出。

比如:

import { Router, Route, routerRedux } from 'dva/router';

dva/fetch

异步请求库,输出 isomorphic-fetch 的接口。不和 dva 强绑定,可以选择任意的请求库。

dva/saga

输出 redux-saga 的接口,主要用于用例的编写。(用例中需要用到 effects)

dva/dynamic

解决组件动态加载问题的 util 方法。

比如:

import dynamic from 'dva/dynamic';

const UserPageComponent = dynamic({
  app,
  models: () => [
    import('./models/users'),
  ],
  component: () => import('./routes/UserPage'),
});

opts 包含:

  • app: dva 实例,加载 models 时需要
  • models: 返回 Promise 数组的函数,Promise 返回 dva model
  • component:返回 Promise 的函数,Promise 返回 React Component

dva API

app = dva(opts)

创建应用,返回 dva 实例。(注:dva 支持多实例)

opts 包含:

  • history:指定给路由用的 history,默认是 hashHistory
  • initialState:指定初始数据,优先级高于 model 中的 state,默认是 {}

如果要配置 history 为 browserHistory,可以这样:

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

另外,出于易用性的考虑,opts 里也可以配所有的 hooks ,下面包含全部的可配属性:

const app = dva({
  history,
  initialState,
  onError,
  onAction,
  onStateChange,
  onReducer,
  onEffect,
  onHmr,
  extraReducers,
  extraEnhancers,
});

app.use(hooks)

配置 hooks 或者注册插件。(插件最终返回的是 hooks )

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

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

hooks 包含:

onError((err, dispatch) => {})

effect 执行错误或 subscription 通过 done 主动抛错时触发,可用于管理全局出错状态。

注意:subscription 并没有加 try...catch,所以有错误时需通过第二个参数 done 主动抛错。例子:

app.model({
  subscriptions: {
    setup({ dispatch }, done) {
      done(e);
    },
  },
});

如果我们用 antd,那么最简单的全局错误处理通常会这么做:

import { message } from 'antd';
const app = dva({
  onError(e) {
    message.error(e.message, /* duration */3);
  },
});

onAction(fn | fn[])

在 action 被 dispatch 时触发,用于注册 redux 中间件。支持函数或函数数组格式。

例如我们要通过 redux-logger 打印日志:

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

onStateChange(fn)

state 改变时触发,可用于同步 state 到 localStorage,服务器端等。

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 };
    },
  },
});

详见 examples/count-undo 。

onEffect(fn)

封装 effect 执行。比如 dva-loading 基于此实现了自动处理 loading 状态。

onHmr(fn)

热替换相关,目前用于 babel-plugin-dva-hmr 。

extraReducers

指定额外的 reducer,比如 redux-form 需要指定额外的 form reducer:

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

extraEnhancers

指定额外的 StoreEnhancer ,比如结合 redux-persist 的使用:

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

app.model(model)

注册 model,详见 #Model 部分。

app.unmodel(namespace)

取消 model 注册,清理 reducers, effects 和 subscriptions。subscription 如果没有返回 unlisten 函数,使用 app.unmodel 会给予警告️。

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 />);

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);

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]

详见: https://github.com/dvajs/dva/blob/master/packages/dva-core/test/reducers-test.js

effects

以 key/value 格式定义 effect。用于处理异步操作和业务逻辑,不直接修改 state。由 action 触发,可以触发 action,可以和服务器交互,可以获取全局 state 的数据等等。

格式为 *(action, effects) => void 或 [*(action, effects) => void, { type }]

type 类型有:

  • takeEvery
  • takeLatest
  • throttle
  • watcher

详见:https://github.com/dvajs/dva/blob/master/packages/dva-core/test/effects-test.js

subscriptions

以 key/value 格式定义 subscription。subscription 是订阅,用于订阅一个数据源,然后根据需要 dispatch 相应的 action。在 app.start() 时被执行,数据源可以是当前的时间、服务器的 websocket 连接、keyboard 输入、geolocation 变化、history 路由变化等等。

格式为 ({ dispatch, history }, done) => unlistenFunction

注意:如果要使用 app.unmodel(),subscription 必须返回 unlisten 方法,用于取消数据订阅。

原文发布时间:2018年03月22日

本文来源CSDN博客如需转载请紧急联系作者

相关文章
|
10天前
|
前端开发 JavaScript 开发者
颠覆传统:React框架如何引领前端开发的革命性变革
【10月更文挑战第32天】本文以问答形式探讨了React框架的特性和应用。React是一款由Facebook推出的JavaScript库,以其虚拟DOM机制和组件化设计,成为构建高性能单页面应用的理想选择。文章介绍了如何开始一个React项目、组件化思想的体现、性能优化方法、表单处理及路由实现等内容,帮助开发者更好地理解和使用React。
36 9
|
15天前
|
前端开发 JavaScript Android开发
前端框架趋势:React Native在跨平台开发中的优势与挑战
【10月更文挑战第27天】React Native 是跨平台开发领域的佼佼者,凭借其独特的跨平台能力和高效的开发体验,成为许多开发者的首选。本文探讨了 React Native 的优势与挑战,包括跨平台开发能力、原生组件渲染、性能优化及调试复杂性等问题,并通过代码示例展示了其实际应用。
43 2
|
17天前
|
前端开发 JavaScript 开发者
React与Vue:前端框架的巅峰对决与选择策略
【10月更文挑战第23天】React与Vue:前端框架的巅峰对决与选择策略
|
17天前
|
前端开发 JavaScript 开发者
“揭秘React Hooks的神秘面纱:如何掌握这些改变游戏规则的超能力以打造无敌前端应用”
【10月更文挑战第25天】React Hooks 自 2018 年推出以来,已成为 React 功能组件的重要组成部分。本文全面解析了 React Hooks 的核心概念,包括 `useState` 和 `useEffect` 的使用方法,并提供了最佳实践,如避免过度使用 Hooks、保持 Hooks 调用顺序一致、使用 `useReducer` 管理复杂状态逻辑、自定义 Hooks 封装复用逻辑等,帮助开发者更高效地使用 Hooks,构建健壮且易于维护的 React 应用。
28 2
|
17天前
|
前端开发 JavaScript 数据管理
React与Vue:两大前端框架的较量与选择策略
【10月更文挑战第23天】React与Vue:两大前端框架的较量与选择策略
|
22天前
|
JavaScript 前端开发 算法
前端优化之超大数组更新:深入分析Vue/React/Svelte的更新渲染策略
本文对比了 Vue、React 和 Svelte 在数组渲染方面的实现方式和优缺点,探讨了它们与直接操作 DOM 的差异及 Web Components 的实现方式。Vue 通过响应式系统自动管理数据变化,React 利用虚拟 DOM 和 `diffing` 算法优化更新,Svelte 通过编译时优化提升性能。文章还介绍了数组更新的优化策略,如使用 `key`、分片渲染、虚拟滚动等,帮助开发者在处理大型数组时提升性能。总结指出,选择合适的框架应根据项目复杂度和性能需求来决定。
|
16天前
|
前端开发 Android开发 开发者
前端框架趋势:React Native在跨平台开发中的优势与挑战
【10月更文挑战第26天】近年来,React Native凭借其跨平台开发能力在移动应用开发领域迅速崛起。本文将探讨React Native的优势与挑战,并通过示例代码展示其应用实践。React Native允许开发者使用同一套代码库同时构建iOS和Android应用,提高开发效率,降低维护成本。它具备接近原生应用的性能和用户体验,但也面临平台差异、原生功能支持和第三方库兼容性等挑战。
28 0
|
17天前
|
前端开发 JavaScript 开发者
React与Vue:前端框架的巅峰对决与选择策略
【10月更文挑战第23天】 React与Vue:前端框架的巅峰对决与选择策略
|
6月前
|
设计模式 前端开发 数据可视化
【第4期】一文了解React UI 组件库
【第4期】一文了解React UI 组件库
355 0
|
6月前
|
资源调度 前端开发 JavaScript
React 的antd-mobile 组件库,嵌套路由
React 的antd-mobile 组件库,嵌套路由
120 0