基于高德数据 tsx-taro 版h5的省市区选择器

451 阅读1分钟

GITHUB 地址

基于高德数据 tsx-taro 版h5的省市区选择器

  • 因为taro picker组件 mode='region' 对于h5实际不兼容,因此通过 multiSelector 进行封装
  • 数据来源高德api
  • 数据类似region.ts 该组件使用接口请求获取数据,可自行改为region中的数据

修改数据重点位置

// 改为不请求接口 直接取 const regionAllTemp = region?.districts?.[0]?.districts;
const res = await getRegion();
if (res) {
    const regionAllTemp = res?.data?.districts?.[0]?.districts;
    ...
}

演示

演示

demo

// 使用
const onReigonChange = (e, obj: TRegionObj) => {
  console.log(e, obj);
};

<RegionPicker
  onReigonChange={onReigonChange}
  initialValues={[1, 2, 0]}
/>

组件代码

.container {
  :global {
    .at-list__item-content {
      width: 20%;
      flex: none;
    }

    .at-list__item-extra {
      display: flex;
      width: 70%;
      max-width: none;
    }
  }
}

import { getRegion } from '@/pages/global/service';
import { Picker, View } from '@tarojs/components';
import { useAsyncEffect } from 'ahooks';
import { FC, useState } from 'react';
import { AtListItem } from 'taro-ui';

import styles from './index.module.less';

export type TRegionObj = {
  /** 选中内容的index数组用于picker value 赋值 */
  regionValue: number[];
  /** 展示的文本 省市区空格隔开 */
  regionText?: string;
  /** 选中内容的数组对象包括 index */
  regionValObjArr: any[];
};

export type TRegionPicker = {
  onReigonChange: (e: any, obj: TRegionObj) => void;
  /** 初始值 默认[0,0,0] */
  initialValues?: number[];
};

const RegionPicker: FC<TRegionPicker> = (props) => {
  const { onReigonChange, initialValues = [] } = props;

  /** 高德省市区全部数据 */
  const [regionAll, setRegionAll] = useState<any[]>([]);
  /** 当前多选各列数据 */
  const [regionData, setRegionData] = useState<any[]>([]);
  /** 选中内容的index数组用于picker value 赋值 */
  const [regionValue, setRegionValue] = useState<any[]>(initialValues);
  const [regionText, setRegionText] = useState('');
  /** 选中内容的数组对象包括 index */
  const [regionValObjArr, setRegionValObjArr] = useState<any[]>([]);

  useAsyncEffect(async () => {
    // 获取高德省市区
    const res = await getRegion();
    if (res) {
      const regionAllTemp = res?.data?.districts?.[0]?.districts;
      setRegionAll(regionAllTemp);
      let range: any = [];
      let temp: any = [];
      for (let i = 0; i < regionAllTemp?.length; i++) {
        temp.push(regionAllTemp?.[i]?.name);
      }
      range.push(temp);
      temp = [];
      for (
        let i = 0;
        i < regionAllTemp?.[regionValue?.[0] || 0]?.districts?.length;
        i++
      ) {
        temp.push(regionAllTemp?.[regionValue?.[0] || 0]?.districts?.[i]?.name);
      }
      range.push(temp);
      temp = [];
      for (
        let i = 0;
        i <
        regionAllTemp?.[regionValue?.[0] || 0]?.districts?.[
          regionValue?.[1] || 0
        ]?.districts?.length;
        i++
      ) {
        temp.push(
          regionAllTemp?.[regionValue?.[0] || 0]?.districts?.[
            regionValue?.[1] || 0
          ]?.districts[i]?.name,
        );
      }
      range.push(temp);
      setRegionData(range);
      const tempObjArr = [
        {
          ...regionAllTemp?.[regionValue?.[0] || 0],
          index: regionValue?.[0] || 0,
        },
        {
          ...regionAllTemp?.[regionValue?.[0] || 0]?.districts?.[
            regionValue?.[1] || 0
          ],
          index: regionValue?.[1] || 0,
        },
        {
          ...regionAllTemp?.[regionValue?.[0] || 0]?.districts?.[
            regionValue?.[1] || 0
          ]?.districts?.[regionValue?.[2] || 0],
          index: regionValue?.[2] || 0,
        },
      ];

      setRegionValObjArr(tempObjArr);
      setRegionText(
        regionValue?.length > 0
          ? `${tempObjArr?.[0]?.name || ''} ${tempObjArr?.[1]?.name || ''} ${
              tempObjArr?.[2]?.name || ''
            }`
          : '',
      );
    }
  }, []);

  const onColumnChange = (e) => {
    let rangeTemp = regionData;
    let valueTemp = regionValue;

    let column = e.detail.column;
    let row = e.detail.value;

    valueTemp[column] = row;

    switch (column) {
      case 0:
        let cityTemp: any = [];
        let districtAndCountyTemp: any = [];
        for (let i = 0; i < regionAll?.[row]?.districts?.length; i++) {
          cityTemp.push(regionAll?.[row]?.districts?.[i]?.name);
        }
        for (
          let i = 0;
          i < regionAll?.[row]?.districts?.[0]?.districts?.length;
          i++
        ) {
          districtAndCountyTemp.push(
            regionAll?.[row]?.districts?.[0]?.districts?.[i]?.name,
          );
        }
        valueTemp[1] = 0;
        valueTemp[2] = 0;
        rangeTemp[1] = cityTemp;
        rangeTemp[2] = districtAndCountyTemp;
        break;
      case 1:
        let districtAndCountyTemp2: any = [];
        for (
          let i = 0;
          i < regionAll?.[valueTemp?.[0]]?.districts?.[row]?.districts?.length;
          i++
        ) {
          districtAndCountyTemp2.push(
            regionAll?.[valueTemp?.[0]]?.districts?.[row]?.districts?.[i]?.name,
          );
        }
        valueTemp[2] = 0;
        rangeTemp[2] = districtAndCountyTemp2;
        break;
      case 2:
        break;
    }
    setRegionData(rangeTemp);

    const tempObjArr = [
      { ...regionAll?.[valueTemp?.[0]], index: valueTemp?.[0] },
      {
        ...regionAll?.[valueTemp?.[0]]?.districts?.[valueTemp?.[1]],
        index: valueTemp?.[1],
      },
      {
        ...regionAll?.[valueTemp?.[0]]?.districts?.[valueTemp?.[1]]
          ?.districts?.[valueTemp?.[2]],
        index: valueTemp?.[2],
      },
    ];

    setRegionValObjArr(tempObjArr);
    setRegionValue([...valueTemp]);
  };

  return (
    <View className={styles.container}>
      <Picker
        mode="multiSelector"
        range={[...regionData]}
        value={regionValue}
        onChange={(e) => {
          const tempRegionText = `${regionValObjArr?.[0]?.name || ''} ${
            regionValObjArr?.[1]?.name || ''
          } ${regionValObjArr?.[2]?.name || ''}`;
          setRegionText(tempRegionText);
          onReigonChange(e, {
            regionValue: e.detail?.value,
            regionText: tempRegionText,
            regionValObjArr,
          });
        }}
        onColumnChange={onColumnChange}
      >
        <AtListItem title="所在地" arrow="right" extraText={regionText} />
      </Picker>
    </View>
  );
};

export default RegionPicker;