前言🐢
看完你能收获🍕
基于umi + dva 的数据处理
- 各层级组件的通信
- 数据mock
的最小最简单最粗糙操作。
本文简单粗暴,就是让你不用看别的,就知道下面这几个东东就能开始整页面。
默认你知道🤔
对react、umi有所了解…基本的函数组件,umi的文件目录能明白是啥,会启动(yarn start)
了解dva😏
dva 首先是一个基于 redux 和 redux-saga 的数据流方案,然后为了简化开发体验,dva 还额外内置了 react-router 和 fetch,所以也可以理解为一个轻量级的应用框架。
#特性
- 易学易用,仅有 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
import React from 'react'//两个子组件import Search from './search'import Lists from './lists'import { connect } from 'dva'const Dva = props => {return (<div>//将父组件的props用展开运算符传入<Search {...props} />/<Lists {...props} /></div>)}//用connect导出ui组件,并将state中的search作为props传入子组件export default connect(({ search }) => ({search,}))(Dva)
ui组件用connect导出。
connect的作用是将组件和models结合在一起,将models中的state绑定到组件的props中。
并提供一些额外的功能,譬如dispatch
最后返回一个 React 组件,通常称为容器组件,即原始 UI 组件的容器,即在外面包了一层 State。
connect 方法传入的第一个参数是 mapStateToProps 函数,该函数需要返回一个对象,用于建立 State 到 Props 的映射关系。】
src/pages/search.js
import React, { useState } from 'react'//本质是封装antd-mobileimport { SearchBar } from 'antd-mobile'//该组件用来做搜索相关的功能const Search = props => {const [value, setValue] = useState('')const handleChange = value => {setValue(value)}const handleSubmit = () => {//console.log('props', value)props.dispatch({//dispatch的选择(命名空间/请求方法标志),以及参数,会去到后面的models文件夹中去找//type: 'search/getLists',type: 'search/getListsAsync',payload: value,})}return (<div><SearchBarautoFocusvalue={value}onChange={handleChange}onSubmit={handleSubmit}/></div>)}export default Search
src/pages/lists.js
import React from 'react'import { List } from 'antd-mobile'//简简单单展示一下const Lists = props => {//console.log(props.search)//从connect来的search...const { text, lists } = props.searchreturn (<div><h1>text:{text}</h1><List>{lists.map((item, i) => (<List.Item key={i}>{item}</List.Item>))}</List></div>)}export default Lists
在src文件夹下创建一个新的子文件夹 models —— 用来存放dva相关的代码。
src/models/search.js
//从services(在后面说)中引用调用异步的方法getListsimport { getLists } from '@/services/search'export default {//命名空间namespace: 'search',//通过connect与ui组件互联的statestate: {text: 'dva',lists: [],},//方法//同步reducers: {getLists(state, action) {return {...state,lists: Array(10).fill(action.payload),}},},//异步effects: {//call 调用异步函数,puts:事件派发*getListsAsync({ payload }, { call, put }) {const res = yield call(getLists, payload)//这里的getLists是引入的异步方法yield put({type: 'getLists',payload: res.lists,})},},}
再创建一个services 文件夹——放置http相关异步请求
这是nodejs的部分,即这里面的console.log() 是输出在终端中的 因为封装的是express 所以其中的写法与express框架相似。
src/services/search.js
这其中的api自然是数据mock
// export const getLists = value => {// return fetch(`/api/getLists?value=${value}`).then(res =>// res.json().catch(err => {// console.error(err)// }),// )// }export const getLists = value => {return fetch(`/api/getListsAsync?value=${value}`).then(res =>res.json().catch(err => {console.error(err)}),)}
mock/search.js
注意他不是在src中的,这mock文件夹是umi自带的。
export default {//value支持函数类型(异步)、json类型(同步)'GET /api/getLists': {lists: ['a', 'b', 'c'],},'GET /api/getListsAsync': (req, res) => {console.log(req)setTimeout(() => {res.json({lists: Array(10).fill(req.query.value),})}, 1000)},}
页面效果
图解
可以看的出来啊,非常的简陋、非常的丑…先凑合着配合理解吧,刚开始用平板写字还是有不习惯啊,以后一定会更好看的。
希望对你有所帮助,有的话点个赞羞辱一下我丑陋的画技吧。
👋
