react结合antd的Cascader组件实现pc端选择城市控件

react结合antd的Cascader组件实现pc端选择城市控件

业务需求,网上找了好多,发现都不太满意,于是自己写了一个

1.实现如下

提示:
数据地址点击 https://xf-1252186245.cos.ap-chengdu.myqcloud.com/data/data.js 复制下来放到组件同级目录,命名data.js就好。

上面地址data.js乱码的话,点击 github仓库地址 https://github.com/l-x-f/react-city-select 将代码克隆到本地,源码里有data.js,也可以直接访问 data.js github仓库地址路径。

依赖: react antd rc-form prop-types等, 先安装依赖,步骤略。

CitySelect.jsx 文件

import React, { Component } from "react";
import { createForm } from "rc-form";
import { Cascader } from "antd";
import city from "./data"; //  数据见上提示
import PropTypes from "prop-types";

//先配置修饰器 没有配置的话用把 @createForm()删掉 
//然后把最后一行 export default CitySelect;  换成 export default createForm()(CitySelect)
@createForm()   
class CitySelect extends Component {
  // props类型检查
  static propTypes = {
    //  监听选择
    onChange: PropTypes.func,
    // 获取选择值
    getSelectedValues: PropTypes.func,
    // 默认值
    value: PropTypes.array
  };

  onCascaderChange = selectedValues => {
    const { onChange, getSelectedValues } = this.props;
    const result = [];
    // 递归查询城市所有数据
    function findCityData(city) {
      city.forEach(item => {
        const { id, label, value, children } = item;
        if (selectedValues.includes(value)) {
          result.push({ id, label, value });
        }
        if (children && children.length) {
          findCityData(children);
        }
      });
    }
    findCityData(city);

    // 分发监听
    onChange && onChange(selectedValues);
    getSelectedValues && getSelectedValues(result);
  };

  componentDidMount() {
    const {
      form: { setFieldsValue },
      value: selectedValues
    } = this.props;

    if (!selectedValues || !selectedValues.length) {
      return;
    }

    const result = [];
    // 递归查询城市名称数据
    function findLabel(children) {
      children.forEach(item => {
        const { label, value, children } = item;
        if (selectedValues.includes(label)) {
          result.push(value);
        }
        if (children && children.length) {
          findLabel(children);
        }
      });
    }
    // 卡省份解决县或市名称一样的问题
    city.forEach(item => {
      const { label, value, children } = item;
      if (selectedValues.includes(label)) {
        result.push(value);
        if (children && children.length) {
          findLabel(children);
        }
      }
    });
    // 设置默认值
    setFieldsValue({ city: result });
  }

  render() {
    const { getFieldProps } = this.props.form;
    return (
      <div>
        <Cascader
          options={city}
          {...getFieldProps("city", {
            onChange: this.onCascaderChange,
            rules: [{ required: true }]
          })}
          placeholder="请选择城市"
        />
      </div>
    );
  }
}

export default CitySelect;

2.使用

import React, { Component } from "react";
import { Form,  Button, message, Icon } from "antd";

import CitySelect from "@/components/CitySelect";

import "./hotel.less";

const FormCreate = Form.create;
const FormItem = Form.Item;

@FormCreate()
class HotelSetting extends Component {
  state = {
    selectedValues: []
  };

  handleReset = () => {
    this.props.form.resetFields();
  };

  // 获取选择值
  getSelectedValues = selectedValues => {
    this.setState({
      selectedValues
    });
  };

  handleSumit = e => {
    const { form } = this.props;

    e.preventDefault();
    form.validateFields((err, formData) => {
      console.log(formData, "formData");
      if (err) {
        message.destroy();
        return message.warning("请完整填写表单");
      }
      const data = {
        ...formData,
        selectedValues: this.state.selectedValues
      };
      console.log(data, "data");
    });
  };

  render() {
    const { getFieldDecorator } = this.props.form;

    const defaultCity = ["陕西省", "西安市", "碑林区"];

    return (
      <Form
        className="custom-form custom-vertical-hotel-form"
        layout="vertical"
        labelAlign="left"
        onSubmit={e => {
          this.handleSumit(e);
        }}
        style={{ background: "#fff", padding: 24 }}
      >
        {/* 数据绑定 拿到的city字段是城市编码  getSelectedValues监听可以拿到选择的数据对象 */}
        <FormItem label="城市选择:">
          {getFieldDecorator("city", {
            initialValue: defaultCity,
            rules: [{ required: true, message: "请选择城市选择" }]
          })(<CitySelect getSelectedValues={this.getSelectedValues} />)}
        </FormItem>

        <FormItem label="城市选择:">
          <CitySelect
            getSelectedValues={this.getSelectedValues}
            value={defaultCity}
          />
        </FormItem>

        <FormItem style={{ paddingBottom: 0 }}>
          <Button type="primary" htmlType="submit">
            <Icon type="arrow-up" />
            保存
          </Button>
        </FormItem>
      </Form>
    );
  }
}

export default HotelSetting;

hotel.less

:global(.custom-vertical-hotel-form .ant-form-item-label) {
  width: 90px;

  vertical-align: top;
}
:global(.custom-vertical-hotel-form .ant-form-item-control-wrapper) {
  width: 340px;
  display: inline-block;
}

3.效果及拿到的值
react结合antd的Cascader组件实现pc端选择城市控件_第1张图片
react结合antd的Cascader组件实现pc端选择城市控件_第2张图片
react结合antd的Cascader组件实现pc端选择城市控件_第3张图片

你可能感兴趣的:(react,antd)