react 组件连动效果_react 三级联动地区选择组件 有木有

news/2024/7/3 3:56:07

项目里正好有一个

bVZxpo?w=1706&h=390

import React, { Component } from 'react';

import PropTypes from 'prop-types';

import classNames from 'classnames';

import Selector from './selector';

import Model from '../model/model';

import * as API from '../constants/api';

class Location extends Component {

static propTypes = {

province: PropTypes.shape({

id: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),

name: PropTypes.string

}),

city: PropTypes.shape({

id: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),

name: PropTypes.string

}),

district: PropTypes.shape({

id: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),

name: PropTypes.string

}),

validating: PropTypes.bool, // 是否验证location值得有效性

static: PropTypes.bool,

hasCode: PropTypes.bool,

required: PropTypes.bool,

onFetchProvinces: PropTypes.func,

onFetchCities: PropTypes.func,

onFetchDistricts: PropTypes.func,

onChangeLocation: PropTypes.func,

onError: PropTypes.func,

onSetState: PropTypes.func

}

static defaultProps = {

province: {},

city: {},

district: {},

static: false,

hasCode: false,

onChangeLocation: () => {},

onError: obj => alert(obj.message),

onSetState: () => {}

}

constructor(props) {

super(props);

this.state = {

provinces: [],

cities: [],

districts: []

};

this.initComponent(props);

this.cacheData = {

provinces: {},

cities: {},

districts: {}

}

}

componentWillReceiveProps(nextProps) {

const { province: nextProvince, city: nextCity, district: nextDistrict } = nextProps;

const { province, city, district } = this.props;

if (nextProvince && (!province || nextProvince.id !== province.id)) {

const provincesCacheData = this.cacheData.provinces;

const citiesCacheData = this.cacheData.cities;

const nextProvinceId = nextProvince.id;

if (citiesCacheData[nextProvinceId]) {

const nextState = { cities: citiesCacheData[nextProvinceId].items };

this.setState(nextState, () => this.props.onSetState(nextState));

} else {

this.handleFetchCities(nextProvinceId);

}

}

if (nextCity && (!city || nextCity.id !== city.id)) {

const citiesCacheData = this.cacheData.cities;

const districtsCacheData = this.cacheData.districts;

const nextProvinceId = nextProvince.id;

const nextCityId = nextCity.id;

if (districtsCacheData[`${nextProvinceId}_${nextCityId}`]) {

const nextState = { districts: districtsCacheData[`${nextProvinceId}_${nextCityId}`].items };

this.setState(nextState, () => this.props.onSetState(nextState));

} else {

this.handleFetchDistricts(nextProvinceId, nextCityId);

}

}

}

fetchProvinces = () => {

return new Promise((resolve, reject) => {

const model = Model.getInstance();

model.url = API.API_FETCH_PROVINCES;

// model.setParam({ countryId: CONSTANTS.CATEGORY_TYPE_COOKING });

model.execute((data) => {

resolve(data.data || []);

}, (err) => {

if ('status' in err && err.status === 0) {

this.props.onError({

status: 'error',

message: '获取省份失败'

});

}

reject();

}, this);

});

}

fetchCities = (provinceId, callback) => {

return new Promise((resolve, reject) => {

const model = Model.getInstance();

model.url = API.API_FETCH_CITIES;

model.setParam({ provinceId, hasCode: this.props.hasCode ? 1 : 0 });

model.execute((data) => {

const cities = [];

for (const city of (data.data.dataList || [])) {

cities.push({ id: city.cityId, name: city.cityName, shouzimu: city.shouzimu });

}

resolve(cities);

}, (err) => {

if ('status' in err && err.status === 0) {

this.props.onError({

status: 'error',

message: '获取城市失败'

});

}

reject();

}, this);

});

}

fetchDistricts = (provinceId, cityId, callback) => {

return new Promise((resolve, reject) => {

const model = Model.getInstance();

model.url = API.API_FETCH_DISTRICTS;

model.setParam({ provinceId, cityId, hasCode: this.props.hasCode ? 1 : 0 });

model.execute((data) => {

resolve(data.data.dataList || []);

}, (err) => {

if ('status' in err && err.status === 0) {

this.props.onError({

status: 'error',

message: '获取市县失败'

});

}

reject();

}, this);

});

}

handleSelectProvince = (provinceId) => {

if (!this.props.province || provinceId !== this.props.province.id) {

const provincesCacheData = this.cacheData.provinces;

const citiesCacheData = this.cacheData.cities;

if (citiesCacheData[provinceId]) {

const nextState = { cities: citiesCacheData[provinceId].items };

this.setState(nextState, () => this.props.onSetState(nextState));

}

const province = { id: provinceId, name: (provincesCacheData[provinceId] || {}).name };

this.props.onChangeLocation({ province, city: null, district: null });

this.setState({ districts: [] }, () => this.props.onSetState({ districts: [] }));

}

}

handleSelectCity = (cityId) => {

if (!this.props.city || cityId !== this.props.city.id) {

const citiesCacheData = this.cacheData.cities;

const districtsCacheData = this.cacheData.districts;

const { province: { id: provinceId } } = this.props;

if (districtsCacheData[`${provinceId}_${cityId}`]) {

const nextState = { districts: districtsCacheData[`${provinceId}_${cityId}`].items };

this.setState(nextState, () => this.props.onSetState(nextState));

}

const city = { id: cityId, name: (citiesCacheData[provinceId][cityId] || {}).name };

this.props.onChangeLocation({ city, district: null });

}

}

handleSelectDistrict = (districtId) => {

const { province: { id: provinceId }, city: { id: cityId } } = this.props;

const districtsCacheData = this.cacheData.districts;

const district = { id: districtId, name: (districtsCacheData[`${provinceId}_${cityId}`][districtId] || {}).name };

this.props.onChangeLocation({ district });

}

handleFetchProvinces = () => {

const fetchProvinces = this.props.onFetchProvinces || this.fetchProvinces;

fetchProvinces().then(provinces => {

this.updatedProvincesToCache(provinces);

const nextState = { provinces: this.cacheData.provinces.items };

this.setState(nextState, () => this.props.onSetState(nextState));

});

}

handleFetchCities = (provinceId) => {

const fetchCities = this.props.onFetchCities || this.fetchCities;

fetchCities(provinceId).then(cities => {

this.updatedCitiesToCache(provinceId, cities);

const nextState = { cities: this.cacheData.cities[provinceId].items };

this.setState(nextState, () => this.props.onSetState(nextState));

});

}

handleFetchDistricts = (provinceId, cityId) => {

const fetchDistricts = this.props.onFetchDistricts || this.fetchDistricts;

fetchDistricts(provinceId, cityId).then(districts => {

this.updatedDistrictsToCache(provinceId, cityId, districts);

const nextState = { districts: this.cacheData.districts[`${provinceId}_${cityId}`].items };

this.setState(nextState, () => this.props.onSetState(nextState));

});

}

initComponent = (props) => {

const { province, city, district } = props;

this.handleFetchProvinces();

if (province.id) {

this.handleFetchCities(province.id);

if (city.id) {

this.handleFetchDistricts(province.id, city.id);

}

}

}

validateProvince = () => {

const { province } = this.props;

return province && province.id;

}

validateCity = () => {

const { city } = this.props;

return (city && city.id) || (this.validateProvince() && (!this.state.cities || !this.state.cities.length) && (!city || !city.id));

}

validateDistrict = () => {

const { district } = this.props;

return (district && district.id) || (this.validateCity() && (!this.state.districts || !this.state.districts.length) && (!district || !district.id));

}

updatedProvincesToCache = (provinces) => {

this.cacheData.provinces = {};

const provincesCacheData = this.cacheData.provinces;

for (const province of (provinces || [])) {

provincesCacheData[province.id] = {

name: province.name,

cities: {}

};

}

provincesCacheData.items = provinces;

}

updatedCitiesToCache = (provinceId, cities) => {

const citiesCacheData = {};

const items = [];

for (const city of (cities || [])) {

citiesCacheData[city.id] = {

name: city.name,

shouzimu: city.shouzimu,

districts: {}

};

items.push({ ...city });

}

citiesCacheData.items = items;

this.cacheData.cities[provinceId] = citiesCacheData;

}

updatedDistrictsToCache = (provinceId, cityId, districts) => {

const districtsCacheData = {};

const items = [];

for (const district of (districts || [])) {

districtsCacheData[district.id] = {

name: district.name

};

items.push({ ...district });

}

districtsCacheData.items = items;

this.cacheData.districts[`${provinceId}_${cityId}`] = districtsCacheData

}

render() {

const province = this.props.province || {};

const city = this.props.city || {};

const district = this.props.district || {};

const { provinces, cities, districts } = this.state;

const { validating } = this.props;

const isProvinceValid = this.validateProvince();

const isCityValid = this.validateCity();

const isDistrictValid = this.validateDistrict();

return (

className={classNames('mw-form-control', { error: !!validating && !isProvinceValid })}

value={province.id}

options={provinces}

valueField="id"

labelField="name"

placeholder="请选择省份"

onChange={this.handleSelectProvince}

/>

className={classNames('mw-form-control', { error: !!validating && !isCityValid })}

value={city.id}

options={cities}

valueField="id"

labelField="name"

placeholder="请选择城市"

onChange={this.handleSelectCity}

/>

className={classNames('mw-form-control', { error: !!validating && !isDistrictValid })}

value={district.id}

options={districts}

valueField="id"

labelField="name"

placeholder="请选择区县"

onChange={this.handleSelectDistrict}

/>

);

}

}

export default Location;


http://www.niftyadmin.cn/n/3142263.html

相关文章

Redis的IO多路复用

一、linux的IO复用函数同一个线程内,多个描述符的IO操作,能够并发交替地顺序执行。epoll只提供三个函数:int epoll_create(int size); #创建epoll句柄int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);关联被监听的事件和…

python -- synonyms

1、安装synonyms 通过pip安装synonyms 需要先安装下 numpy、scikit-learn、scipy 直接使用pip极可能安装失败,这里推荐下载.whl文件进行安装 https://www.lfd.uci.edu/~gohlke/pythonlibs/ 下载对应版本的文件 使用pip安装 pip install "a.whl" 若安装还…

高性能mysql 笔记_高性能Mysql笔记 — 优化

性能优化了解查询的整个生命周期,清楚每个阶段的时间消耗情况性能分析慢查询日志——服务器性能分析参考慢查询日志是优化很重要的手段,但是开启慢查询日志对性能的影响并不大,所以可以考虑在线上打开慢查询日志查看慢查询是否打开、以及日志…

区块链文章链接

2019独角兽企业重金招聘Python工程师标准>>> 想把区块链文章从知乎转移到OSCHINA, OSCHINA每天有篇数限制, 更多的文章暂时请到知乎查看: https://www.zhihu.com/people/zxvf-73/posts 转载于:https://my.oschina.net/kingwjb/blo…

TCHAR和CHAR类型的互转,string 转lpcwstr

https://www.cnblogs.com/yuguangyuan/p/5955959.html 没有定义UNICODE,所以它里面的字符串就是简单用" "就行了,创建工程的时候包含了UNICODE定义,就必须对TCHAR和char进行转换。 void TcharToChar(const TCHAR * tchar, char * _…

java gui 计算器_利用Java GUI 实现简单的计算器

importjava.awt.EventQueue;importjavax.swing.JFrame;importjavax.swing.JButton;importjavax.swing.JTextField;importjava.awt.event.ActionListener;importjava.awt.event.ActionEvent;/*** GUI计算器*authorAdministrator**/public classCalculater {static float sum 0f;…

我的PMP备考历程

上下寻觅,偶遇PMP从事项目管理相关工作近八年,期间零星学习了一些项目管理的相关知识,在项目管理实际工作中,发现已有的项目管理知识越来越不能满足实际工作的需求,感觉有些力不从心,于是萌生了系统学习项目…

【项目执行】项目中问题

多部门,多人员参与 1.确定项目总负责人,及时协调各方任务和人力2.晨会沟通当天任务,同步项目进展(15min,晨会不做小组讨论)3.日报同步项目进度和风险,已知风险确定解决方案或解决时间(下班前) 前…