• react 省市区下拉组件的思考


    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。

    讲的很粗糙,还是仔细研究下代码吧,这种写法 可以很方便的封装一部分重复代码,减少重复的工作量(虽然对于新手来说增加了理解成本,但是用习惯以后,发现还真是因吹斯听呢)

  • 相关阅读:
    数据结构之线段树
    数据结构之线段树
    数据结构之树状数组
    codevs1073 家族
    codevs1069 关押罪犯
    codevs1001 舒适的路线
    codevs1282 约瑟夫问题
    codevs1081 线段树练习 2
    codevs1225 八数码难题
    codevs1080 线段树练习
  • 原文地址:https://www.cnblogs.com/aleafo/p/10728425.html
Copyright © 2020-2023  润新知