react-native 封装城市选择组件(一)

338 阅读2分钟

由于工作的原因,昨天的直播暂时缓一缓,今天先为工作做一个准备。

首先我城市组件支持的数据格式:

[//权限内的区域权限
  {
      "name": "北京市",
      "items": [
          {
              "name": "北京市",
              "items": [
                  {
                      "name": "石景山区",
                  },
                  {
                      "name": "怀柔区",
                  },
              ]
          }
      ]
  },
  {
      "name": "河北省",
      "items": [
          {
              "name": "石家庄市",
              "items": [
                  {
                      "name": "新华区",
                  }

              ]
          }
      ]
  },
  {
      "name": "吉林省",
      "items": [
          {
              "name": "吉林市",
              "items": [
                  {
                      "name": "船营区",
                  }
              ]
          }
      ]
  },
  {
      "name": "上海市",
      "items": [
          {
              "name": "上海市",
              "items": [
                  {
                      "name": "黄浦区",
                  }
              ]
          }
      ]
  }
]

今天只是先把模型弄出来,并不是最终的版本。

我使用一个 FlatList 完成下面的效果:

我要设计的这个城市选择组件支持自定义数据源,自定义宽度,自定义初次进入默认选中的省份,自定义等级,比如分三栏,也可以自定义分四栏。下面是定义选中的数组:

const [indexes, setIndexes] = useState([0, 0, 1]);

我这里默认使用三栏来举例,当时候全部封装完成以后能够根据数据来确定这个数组。

接下来看布局部分:

<View
  style={{
    flexDirection: 'row',
    alignItems: 'center',
    backgroundColor: '#ccc',
    marginTop: 80,
  }}>
  <Text>返回</Text>
  <Text>选择城市</Text>
</View>
<ScrollView horizontal={true}>
  <View style={{flex: 1, flexDirection: 'row', backgroundColor: '#fff'}}>
    {[0, 0, 0].map((items, index) => {
      return (
        <FlatList
          style={{
            backgroundColor: `#${index + 5}0${index + 5}`,
            height: '100%',
            width: Dimensions.get('screen').width / 3,
          }}
          data={selectData(index, indexes)}
          renderItem={({item, index: i}) => {
            return (
              <Text
                onPress={() => {
                  setIndexes((indexes) => {
                    indexes[index] = i;
                    for (let i = index + 1; i < 3; i++) {
                      indexes[i] = 0;
                    }
                    return [...indexes];
                  });
                }}
                style={{
                  padding: 20,
                  backgroundColor: indexes[index] === i ? '#fff' : 'red',
                  marginVertical: 10,
                }}>
                {item?.name}
              </Text>
            );
          }}
        />
      );
    })}
  </View>
</ScrollView>

最重要的就是上边的 selectData 函数,这个函数就是自动选择此时应该渲染那一层:

const selectData = (index, indexes) => {
  let tempData = data;
  for (let i = 0; i < index; i++) {
    tempData = tempData[indexes[i]].items;
  }
  return tempData;
};

主要是根据当前循环到的 index ,根据这个自动向数据深处寻找数据。

之所以记录这个,一个很重要的原因是以前渲染我都是从上到下,从左到右的方式进行。虽然我写的这个也的确也遵从上面的原则,但是达到了一次遍历却能做到全部渲染,而且渲染给我们感觉就是一行一行的进行。这个跟我们公司的组织架构一样,表面上看我属于某一个项目组,实际上是我还是属于某一个部门,然后再到项目组。