前言🐢

看完你能收获🍕

基于umi + dva 的数据处理

  • 各层级组件的通信
  • 数据mock

的最小最简单最粗糙操作。
本文简单粗暴,就是让你不用看别的,就知道下面这几个东东就能开始整页面。

默认你知道🤔

对react、umi有所了解…基本的函数组件,umi的文件目录能明白是啥,会启动(yarn start)

了解dva😏

dvajs官网

dva 首先是一个基于 reduxredux-saga 的数据流方案,然后为了简化开发体验,dva 还额外内置了 react-routerfetch,所以也可以理解为一个轻量级的应用框架。

#特性

  • 易学易用,仅有 6 个 api,对 redux 用户尤其友好,配合 umi 使用后更是降低为 0 API
  • elm 概念,通过 reducers, effects 和 subscriptions 组织 model
  • 插件机制,比如 dva-loading 可以自动处理 loading 状态,不用一遍遍地写 showLoading 和 hideLoading
  • 支持 HMR,基于 babel-plugin-dva-hmr 实现 components、routes 和 models 的 HMR

图解dva
就是这东东没有新的概念和api,就是基于redux等东东的封装,所以非常好上手。


快速上手🐱‍🏍

我会想带你配置一下,并且创建几个文件,我再一个个解释,看完你至少能套着我这份最简单最小的demo进行小小的开发。最后也会有一张图解全貌。
umi自带dva,但在配合umi时,要记得在.umirc.js配置中打开 dva 开关。

还用到了umi自带的,也要打开antd

几个文件

先复制了,然后看结合最后的图解看代码注释,可以自己浅画一下各个组件的联系。

src/pages/dva/index.js

  1. import React from 'react'
  2. //两个子组件
  3. import Search from './search'
  4. import Lists from './lists'
  5. import { connect } from 'dva'
  6. const Dva = props => {
  7. return (
  8. <div>
  9. //将父组件的props用展开运算符传入
  10. <Search {...props} />/
  11. <Lists {...props} />
  12. </div>
  13. )
  14. }
  15. //用connect导出ui组件,并将state中的search作为props传入子组件
  16. export default connect(({ search }) => ({
  17. search,
  18. }))(Dva)

ui组件用connect导出。
connect的作用是将组件和models结合在一起,将models中的state绑定到组件的props中。
并提供一些额外的功能,譬如dispatch
最后返回一个 React 组件,通常称为容器组件,即原始 UI 组件的容器,即在外面包了一层 State。

connect 方法传入的第一个参数是 mapStateToProps 函数,该函数需要返回一个对象,用于建立 State 到 Props 的映射关系。】

src/pages/search.js

  1. import React, { useState } from 'react'
  2. //本质是封装antd-mobile
  3. import { SearchBar } from 'antd-mobile'
  4. //该组件用来做搜索相关的功能
  5. const Search = props => {
  6. const [value, setValue] = useState('')
  7. const handleChange = value => {
  8. setValue(value)
  9. }
  10. const handleSubmit = () => {
  11. //console.log('props', value)
  12. props.dispatch({
  13. //dispatch的选择(命名空间/请求方法标志),以及参数,会去到后面的models文件夹中去找
  14. //type: 'search/getLists',
  15. type: 'search/getListsAsync',
  16. payload: value,
  17. })
  18. }
  19. return (
  20. <div>
  21. <SearchBar
  22. autoFocus
  23. value={value}
  24. onChange={handleChange}
  25. onSubmit={handleSubmit}
  26. />
  27. </div>
  28. )
  29. }
  30. export default Search

src/pages/lists.js

  1. import React from 'react'
  2. import { List } from 'antd-mobile'
  3. //简简单单展示一下
  4. const Lists = props => {
  5. //console.log(props.search)
  6. //从connect来的search...
  7. const { text, lists } = props.search
  8. return (
  9. <div>
  10. <h1>text:{text}</h1>
  11. <List>
  12. {lists.map((item, i) => (
  13. <List.Item key={i}>{item}</List.Item>
  14. ))}
  15. </List>
  16. </div>
  17. )
  18. }
  19. export default Lists

在src文件夹下创建一个新的子文件夹 models —— 用来存放dva相关的代码。
src/models/search.js

  1. //从services(在后面说)中引用调用异步的方法getLists
  2. import { getLists } from '@/services/search'
  3. export default {
  4. //命名空间
  5. namespace: 'search',
  6. //通过connect与ui组件互联的state
  7. state: {
  8. text: 'dva',
  9. lists: [],
  10. },
  11. //方法
  12. //同步
  13. reducers: {
  14. getLists(state, action) {
  15. return {
  16. ...state,
  17. lists: Array(10).fill(action.payload),
  18. }
  19. },
  20. },
  21. //异步
  22. effects: {
  23. //call 调用异步函数,puts:事件派发
  24. *getListsAsync({ payload }, { call, put }) {
  25. const res = yield call(getLists, payload)//这里的getLists是引入的异步方法
  26. yield put({
  27. type: 'getLists',
  28. payload: res.lists,
  29. })
  30. },
  31. },
  32. }

再创建一个services 文件夹——放置http相关异步请求

这是nodejs的部分,即这里面的console.log() 是输出在终端中的 因为封装的是express 所以其中的写法与express框架相似。

src/services/search.js
这其中的api自然是数据mock

  1. // export const getLists = value => {
  2. // return fetch(`/api/getLists?value=${value}`).then(res =>
  3. // res.json().catch(err => {
  4. // console.error(err)
  5. // }),
  6. // )
  7. // }
  8. export const getLists = value => {
  9. return fetch(`/api/getListsAsync?value=${value}`).then(res =>
  10. res.json().catch(err => {
  11. console.error(err)
  12. }),
  13. )
  14. }

mock/search.js
注意他不是在src中的,这mock文件夹是umi自带的。

  1. export default {
  2. //value支持函数类型(异步)、json类型(同步)
  3. 'GET /api/getLists': {
  4. lists: ['a', 'b', 'c'],
  5. },
  6. 'GET /api/getListsAsync': (req, res) => {
  7. console.log(req)
  8. setTimeout(() => {
  9. res.json({
  10. lists: Array(10).fill(req.query.value),
  11. })
  12. }, 1000)
  13. },
  14. }

页面效果

image.png

图解

可以看的出来啊,非常的简陋、非常的丑…先凑合着配合理解吧,刚开始用平板写字还是有不习惯啊,以后一定会更好看的。
Screenshot_20220125_231229_com.jideos.jnotes.png




希望对你有所帮助,有的话点个赞羞辱一下我丑陋的画技吧。
👋