资讯专栏INFORMATION COLUMN

初识React(9):dva简介

keke / 1841人阅读

摘要:初始值,优先级低于传给的,如下此时,在后为以格式定义。用于处理同步操作,唯一可以修改的地方。由触发,可以触发,可以和服务器交互,可以获取全局的数据等等。取消注册,清理和。如果没有返回函数,使用会给予警告注册路由表。

前言

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

推荐把路由信息抽成一个多带带的文件,这样结合 babel-plugin-dva-hmr 可实现路由和组件的热加载,比如:

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

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

app.router(() => );
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(, htmlElement);

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

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/100138.html

相关文章

  • 初识React(6):propTypes类型检测

    摘要:是中用来对参数进行类型检测的,当然要使用这个插件,得先安装这个插件,如下但是如果你是直接用创建的项目,无需安装,直接引入即可,如下上面那个例子中可以看出,要引入组件,必须得传入参数类型为字符串的参数,否则会报错常用的数据类型检测如下 propTypes是react中用来对参数进行类型检测的,当然要使用这个插件,得先安装这个插件,如下: npm install prop-types --...

    Brenner 评论0 收藏0
  • 初识React(3):组件

    摘要:创建组件创建组件之前要注意以下几点组件创建的名称首字母得大写组件中返回的只能是一个根节点,所有的内容得用一个元素都框起来无状态函数式组件无状态函数式组件可以理解成就是一个函数生成的,使得代码的可读性更好,并且精简便利,减少了冗余,无状态组件 创建组件 创建组件之前要注意以下几点: 组件创建的名称首字母得大写 组件中返回的JSX只能是一个根节点,所有的内容得用一个元素都框起来 1.无...

    FullStackDeveloper 评论0 收藏0
  • 一篇文章读懂 React & redux 前端开发

    摘要:如在中在中,聚合积累的结果是当前的对象。被称为副作用,在我们的应用中,最常见的就是异步操作。至于为什么我们这么纠结于纯函数,如果你想了解更多可以阅读,或者它的中文译本函数式编程指南。 DvaJS: React and redux based, lightweight and elm-style framework. https://dvajs.com/ 实例项目源码:https://g...

    cppowboy 评论0 收藏0
  • dva开发一个cnode网站(1)

    摘要:首先是一个基于和的数据流方案,然后为了简化开发体验,还额外内置了和,所以也可以理解为一个轻量级的应用框架。本教程是利用的开放来做一个一样的网站,以此来学习框架的使用。写的不好的地方还请多多包涵,大家一起学习。 dva 首先是一个基于 redux 和 redux-saga 的数据流方案,然后为了简化开发体验,dva 还额外内置了 react-router 和 fetch,所以也可以理解为...

    marek 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<