async js 返回值_dva.js初探

70516ff75aa9c9ba9f74e884a731dff7.png

dva是一个在reduxredux-saga的基础上封装的一个轻型框架,能辅助更好的组织代码进行开发。同时提供了react-routerfetch,基本上具备了开发web前端应用所需的主要工具,省下开发者自己进行配置安装的工作。

开始使用dva

首先使用dva-cli快速创建dva应用。

npm install dva-cli -g

使用dva快速创建新的项目框架。

dva new my-new-project

dva会默认使用tnpm, cnpm依赖安装,由于我现在的tnpm不能使用,只能把tnpm删掉。

问题:如何配置dva的默认npm源

项目结构

dva-cli会创建如下的初始化项目结构

.
├── .editorconfig
├── .eslintrc
├── .gitignore
├── .roadhogrc.mock.js
├── .webpackrc    // webpack 配置
├── mock
│   └── .gitkeep
├── package.json
├── public
│   └── index.html
└── src
    ├── assets
    │   └── yay.jpg
    ├── components
    │   └── Example.js
    ├── index.css
    ├── index.js
    ├── models
    │   └── example.js    // 数据(状态)管理中心
    ├── router.js    // 路由
    ├── routes
    │   ├── IndexPage.css
    │   └── IndexPage.js    // 路由中对应的页面入口
    ├── services
    │   └── example.js
    └── utils
        └── request.js

接下来根据我的个人喜好对项目进行微调 * 加入pages目录,区别于components,前者用于放置页面的个性化组件,后者用于放置复用性强的公共组件。然而这种组织一定程度上使得routes的存在没有太大的意义。

在dva中使用redux

如果决定使用redux的话,需要在src/index.js里加入要用的model

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

在dva中使用redux-router

router.js中将页面入口组件引入并配置相关的路由

import IndexPage from './routes/IndexPage';
import ManagerPage from './routes/ManagerPage';
import EntryPage from './routes/EntryPage';

function RouterConfig({ history }) {
  return (
    <Router history={history}>
      <Switch>
          <Route path="/user" exact component={IndexPage} />
          <Route path="/manager" exact component={ManagerPage} />
          <Route path="/entry" exact component={EntryPage} />
      </Switch>
    </Router>
  );
}

在model中使用redux-router

import { routerRedux } from 'dva/router';

put(routerRedux.push('/manager'))

routerRedux.push('/manager')

在组件中使用redux-router

import { routerRedux } from 'dva/router';

dispatch(routerRedux.push('/manager'))

接下来就可以愉快的开发了。

dva中的redux

首先,在使用dva开发时,可以将store拆分为多个model,每个model对应一个namespace,对于复杂的应用,这种组织方式更贴近逻辑,使得问题更为清晰。对比我之前在vue中将store拆为state, getters, mutations, actions要更科学一些。后者的查分方式可以成为“横向拆分”, 而前者的拆分方式则是一种“纵向拆分”。 这种纵向拆分使得每一个拆分出来的子集都是一个子服务的对应。该自己可以包含自己的statereducerseffects,可以认为是一种前端微服务化的思想。

dvastore的构成与vuex相似,都将同步reducers和异步reducers拆分开来,以更好的管理监控异步操作。dva在异步处理上使用了redux-saga,借助Genarator来实现异步操作。

问题:为什么不使用async呢?是历史问题,还是二者在细节层面存在差别。

generator函数的使用

关于Generator Generator使用*标识函数为Generator函数 使用yield阻断异步操作,等到yield后的表达式完成计算得到返回值时,再继续执行下面的代码。 关于是否要对同步操作使用yield,我认为没有严格的限制。但如果其中存在你所关心的中间状态变量,可以加上yield。这样就可以在调用next()方法时在返回对象的value属性中查询到。

这点与async不同,async返回的是promise,而generator返回的则是状态对象

redux-saga中异步effects的函数有三个参数

*postFile({ payload }, {call, put}) {
      // handle both create and update
      let res = yield call(fetch, '//api.center/postFile', {
        method: 'post',
        headers: {
          'Content-Type': 'application/json'
        },
        body: JSON.stringify(payload)
      })
      let result = yield res.json()
      if (result.success) {
        yield put({ type: 'getFileList' })
      }
    },
  • { payload } = action, 调用dispatch时所传递的参数
  • {call, put} call负责调用异步操作,put则调用其他reducers来完成对state的修改操作
    • 这与vuex不同,vuex中的action可以直接修改state(也可以调用mutations),但直接修改会导致action的逻辑过于复杂,失去了分段调试监控的优势。
  • call(异步操作函数,参数1,参数2,...) return 异步函数的返回值(promise或值)
  • put({type, payload})dispatch参数相同,但type中不需要定义命名空间

reducers的设计

dva给出的实例代码中,有一个reducers的定义十分有趣

save(state, action) {
  return { ...state, ...action.payload };
}

这种实现是对所有reducers的本质抽象,即修改state。在实践简单应用的开发时,基本上所有的reducers都可以只用这一个save来实现。那是不是无需编写其他的reducers了呢? 我认为不是的,对于如下情况,仍需对每一种情况编写对应的reducers 修改的状态(state)过多,导致难以通过修改值直接判断reducer所代表的逻辑是什么(在哪里调用,为什么调用)。这种情况下建议新定义reducer,对一个state的操作集进行封装,以便在调试时清楚被调用的reducer对应的业务逻辑是什么。 需要根据参数进行预计算,最终得到state。这时,建议将一些重要的逻辑运算迁移到reducer中,以方便管理或复用。

开放的webpack配置

.webpackrc使得可以根据个人需求对react进行配置而无需进行eject操作。 (也可以将.webpackrc改为.webpackrc.json从而使用json格式的配置) 如,我们可以配置babel插件来直接引入如antdnext之类的框架

{
   "extraBabelPlugins": [
    ["import", {
      "libraryName": "antd",
      "libraryDirectory": "es",
      "style": true
    }]
  ]
}

如果不想使用css modules功能 (比如next的import配置失败,只能手动导入css),还可以加入

"disableCSSModules": true

不过,建议体验一下css modules的功能

import styles from './style.css';

<h1 className={styles.bgRed}>Hello React!</h1>

参考资料

Dva官网:https://dvajs.com/guide/

ES6 Generator:http://es6.ruanyifeng.com/#docs/generator

dva.js入门 https://www.jianshu.com/p/c7b3b9c98d04

antd配置:https://ant.design/docs/react/introduce-cn react eject:https://github.com/facebook/create-react-app/blob/master/packages/react-scripts/template/README.md#npm-run-eject

redux saga:https://redux-saga-in-chinese.js.org/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值