import React, { PureComponent } from 'react'; import { Select, Spin } from 'antd'; import { connect } from 'dva'; import styles from './GeographicView.less'; const { Option } = Select; const nullSlectItem = { label: '', key: '', }; @connect(({ geographic }) => { const { province, isLoading, city, area } = geographic; return { province, city, area, isLoading, }; }) class GeographicView extends PureComponent { componentDidMount = () => { const { dispatch } = this.props; dispatch({ type: 'geographic/fetchProvince', }); }; componentDidUpdate(props) { const { dispatch, value } = this.props; if (!props.value && !!value && !!value.province) { dispatch({ type: 'geographic/fetchCity', payload: value.province.key, }); } } getProvinceOption() { const { province } = this.props; return this.getOption(province); } getCityOption = () => { const { city } = this.props; return this.getOption(city); }; getAreaOption = () => { const { city } = this.props; return this.getOption(city); }; getOption = list => { if (!list || list.length < 1) { return ( <Option key={0} value={0}> 没有找到选项 </Option> ); } return list.map(item => ( <Option key={item.id} value={item.id}> {item.name} </Option> )); }; selectProvinceItem = item => { const { dispatch, onChange } = this.props; dispatch({ type: 'geographic/fetchProvince', payload: item.key, }); onChange({ province: item, city: nullSlectItem, area: nullSlectItem, }); }; selectCityItem = item => { const { dispatch, onChange, value } = this.props; dispatch({ type: 'geographic/fetchCity', payload: item.key, }); onChange({ province: value.province, city: item, area: nullSlectItem, }); }; selectAreaItem = item => { const { value, onChange } = this.props; onChange({ province: value.province, city: value.city, area: item, }); }; conversionObject() { const { value } = this.props; if (!value) { return { province: nullSlectItem, city: nullSlectItem, area: nullSlectItem, }; } const { province, city, area } = value; return { province: province || nullSlectItem, city: city || nullSlectItem, area: area || nullSlectItem, }; } render() { const { province, city, area } = this.conversionObject(); const { isLoading } = this.props; return ( <Spin spinning={isLoading} wrapperClassName={styles.row}> <Select className={styles.item} value={province} labelInValue showSearch onSelect={this.selectProvinceItem} > {this.getProvinceOption()} </Select> <Select className={styles.item} value={city} labelInValue showSearch onSelect={this.selectCityItem} > {this.getCityOption()} </Select> <Select className={styles.item} value={area} labelInValue showSearch onSelect={this.selectAreaItem} > {this.getAreaOption()} </Select> </Spin> ); } } export default GeographicView;
先上代码, 上面一段是 GeographicView.js
import { queryProvince, queryCity } from '@/services/geographic'; export default { namespace: 'geographic', state: { province: [], city: [], area: [], isLoading: false, }, effects: { *fetchProvince(_, { call, put }) { yield put({ type: 'changeLoading', payload: true, }); const response = yield call(queryProvince); yield put({ type: 'setProvince', payload: response, }); yield put({ type: 'changeLoading', payload: false, }); }, *fetchCity({ payload }, { call, put }) { yield put({ type: 'changeLoading', payload: true, }); const response = yield call(queryCity, payload); yield put({ type: 'setCity', payload: response, }); yield put({ type: 'changeLoading', payload: false, }); }, *fetchArea({ payload }, { call, put }) { yield put({ type: 'changeLoading', payload: true, }); const response = yield call(queryCity, payload); yield put({ type: 'setArea', payload: response, }); yield put({ type: 'changeLoading', payload: false, }); }, }, reducers: { setProvince(state, action) { return { ...state, province: action.payload, }; }, setCity(state, action) { return { ...state, city: action.payload, }; }, setArea(state, action) { return { ...state, area: action.payload, }; }, changeLoading(state, action) { return { ...state, isLoading: action.payload, }; }, }, };
上面是models数据, 基于dva(redux以及saga的集成就不再详述了)
view中的部分, 关于下面一行代码的思考。
const { province, city, area } = this.conversionObject();
这里的this调用
conversionObject() { const { value } = this.props; if (!value) { return { province: nullSlectItem, city: nullSlectItem, area: nullSlectItem, }; } const { province, city, area } = value; return { province: province || nullSlectItem, city: city || nullSlectItem, area: area || nullSlectItem, }; }
该函数, 从而获取到了value的值(注意,这里的value是redux中通过models传递的 state里面的值哦(我也是刚发现还可以这么玩)
但是如果你在函数体内部输出this.props的话其实是输出为空的。 而在 render内调用则使用它的上下文也就是 class,因此能取到 props。
讲的很粗糙,还是仔细研究下代码吧,这种写法 可以很方便的封装一部分重复代码,减少重复的工作量(虽然对于新手来说增加了理解成本,但是用习惯以后,发现还真是因吹斯听呢)