react native 省市区联动

仿京东的省市区联动
封装的组件AddressSelect.js

export default class AddressSelect extends Component {

    static defaultProps = {
        commitFun: function (value) {
            console.log(value);
        },
        dissmissFun: function () {

        },
        lastAddress: null,
    };

    
    constructor(props) {
        super(props);
        //LayoutAnimation - layout动画
        //安卓平台使用 LayoutAnimation 动画必须加上这么一句代码 UIManager.setLayoutAnimationEnabledExperimental
        if (Platform.OS === 'android') {
            // UIManager.setLayoutAnimationEnabledExperimental(true)
        }
        const { lastAddress } = props;
        let selectAddress = this.initAddress(lastAddress);
        this.state = {
            selectAddress
        }
    }

    initAddress(lastAddress) {
        let selectAddress = [
            {
                value: null,
                label: null,
                children: AREA_JSON,
            }, {
                value: null,
                label: null,
                children: null,
            }, {
                value: null,
                label: null,
                children: null,
            }];
        let array = null;

        function fun(array, value) {
            for (let item of array) {
                if (item.value + '' === value + '') {
                    return item;
                }
            }
        }
        try {
            selectAddress = selectAddress.map((item, index) => {
                let result = fun(array ? array : AREA_JSON, lastAddress[index].value);
                if (result.children) {
                    array = result.children;
                }
                return result;
            });
        } catch (e) {
            console.log('-----e-', e);
        }
        return selectAddress
    }


    /**
     * 列表行
     * @param item
     * @param i
     * @returns {XML}
     */
    renderListItem(item, i) {
        let itemStyle = styles.itemStyle;
        let textStyle = styles.itemText;
        let { selectAddress } = this.state;
        if (item.label === selectAddress[i].label) {
            itemStyle = [itemStyle];
            textStyle = [textStyle, { color: 'red' }]
        }
        return (
            <TouchableOpacity
                style={itemStyle}
                key={i + item.label}
                onPress={() => {
                    this.pressItem(item, i)
                }}>
                <Text style={textStyle}>{item.label}</Text>
            </TouchableOpacity>
        )
    }

    /**
     * 点击列表事件
     * @param item 选中数据
     * @param i 选中行数
     */
    pressItem(item, i) {
        let { selectAddress } = this.state;
        const initObj = {
            value: null,
            label: null,
            children: null,
        }
        let tempIndex = 0;
        if (i === 0) {
            selectAddress[0] = item;
            selectAddress[1] = initObj;
            selectAddress[2] = initObj;
            tempIndex = 1
        } else if (i === 1) {
            selectAddress[1] = item;
            selectAddress[2] = initObj;
            tempIndex = 2
        } else {
            selectAddress[2].value = item.value;
            selectAddress[2].label = item.label;
            tempIndex = 2;
            let address = [
                {
                    label: selectAddress[0].label,
                    value: selectAddress[0].value
                },
                {
                    label: selectAddress[1].label,
                    value: selectAddress[1].value
                },
                {
                    label: selectAddress[2].label,
                    value: selectAddress[2].value
                }
            ];
            this.props.commitFun && this.props.commitFun(address);
            this.props.dissmissFun && this.props.dissmissFun();
            return null;

        }
        this.setState({ selectAddress });
        InteractionManager.runAfterInteractions(() => {
            this.tabView.goToPage(tempIndex)
        })

    }

    render() {
        const { selectAddress } = this.state;
        return (
            <View style={styles.container}>
                <View style={{ width: width, height: 40, flexDirection: 'row', justifyContent: 'center', alignItems: 'center', }}>
                    <Text>所在地区</Text>
                </View>
                <ScrollableTabView
                    ref={(tabView) => {
                        this.tabView = tabView;
                    }}
                    renderTabBar={() => <SelectCityTabBar />}>
                    {selectAddress.map((obj, i) => {
                        let array = (i === 0) ? AREA_JSON : selectAddress[i - 1].children;
                        if (array) {
                            return (
                                <ScrollView
                                    key={i}
                                    tabLabel={obj.label || '请选择'}
                                    style={styles.scrollStyleList}>

                                    {array && array.map((obj2, j) => {
                                        return this.renderListItem(obj2, i)
                                    })}
                                </ScrollView>
                            )
                        }
                    })}
                </ScrollableTabView>
            </View>
        );
    }
}

样式:

const styles = StyleSheet.create({
    container: {
        height: height * 0.6,
        backgroundColor: '#F5FCFF',
    },
    scrollStyleList: {
        width: width,
        marginBottom: 10,
        marginTop: 10,
    },
    itemStyle: {
        marginTop: 5,
        width: width,
        height: 35,
        marginLeft: 10,
        justifyContent: 'center'
    },
    itemText: {
        fontSize: 15,
        color: '#333333'
    },
});

父组件的使用

 render() {

        return (
            <TouchableOpacity style={{flex: 1, justifyContent: 'center', alignItems: 'center'}}
                              onPress={() => this.openAddressSelect()}>

                <Text>地址选择</Text>
                <AddressSelect
                    commitFun={(area) => this.onSelectArea(area)}
                    dissmissFun={() => {
                    }}
                />
            </TouchableOpacity>
        )
    }

另:
SelectCityTabBar.js

export default class SelectCityTabBar extends Component {
    //属性声名
    static propTypes = {
        goToPage: PropTypes.func,
        activeTab: PropTypes.number,
        tabs: PropTypes.array,
        backgroundColor: PropTypes.string,
        activeTextColor: PropTypes.string,
        inactiveTextColor: PropTypes.string,
        textStyle: Text.propTypes.style,
        tabStyle: ViewPropTypes.style,
        renderTab: PropTypes.func,
        underlineStyle: ViewPropTypes.style,
    };
    //默认属性
    static defaultProps = {
        activeTextColor: '#FA3D4F',
        inactiveTextColor: 'black',
        backgroundColor: null,
    };

    renderTab(name, page, isTabActive, onPressHandler) {
        const {activeTextColor, inactiveTextColor, textStyle,} = this.props;
        const textColor = isTabActive ? activeTextColor : inactiveTextColor;
        const fontWeight = isTabActive ? 'bold' : 'normal';
        const viewStyle = isTabActive ? [styles.tab, {borderBottomWidth: 1, borderColor: BlackTextColor}] : styles.tab;

        if (Platform.OS !== 'ios') {
            return <TouchableNativeFeedback
                delayPressIn={0}
                background={TouchableNativeFeedback.SelectableBackground()}
                key={name + page}
                accessible={true}
                accessibilityLabel={name}
                accessibilityTraits='button'
                onPress={() => onPressHandler(page)}>

                <View style={viewStyle}>
                    <Text style={[{color: textColor, fontWeight,}, textStyle,]}>
                        {name}
                    </Text>
                </View>
            </TouchableNativeFeedback>
        }

        return <TouchableOpacity
            key={name + page}
            accessible={true}
            accessibilityLabel={name}
            accessibilityTraits='button'
            onPress={() => onPressHandler(page)}>

            <View style={viewStyle}>
                <Text style={[{color: textColor, fontWeight,}, textStyle,]}>
                    {name}
                </Text>
            </View>
        </TouchableOpacity>;
    }

    render() {
        return (
            <View style={{
                flexDirection: 'row',
                borderBottomWidth: 1,
                borderColor: BlackTextColor
            }}>
                {this.props.tabs.map((name, page) => {
                    const isTabActive = this.props.activeTab === page;
                    const renderTab = this.props.renderTab || this.renderTab;
                    return this.renderTab(name, page, isTabActive, this.props.goToPage);
                })}
            </View>
        );
    }
}

const styles = StyleSheet.create({
    tab: {
        alignItems: 'center',
        justifyContent: 'center',
        paddingBottom: 10,
        marginLeft: 10,
    },
    tabs: {
        height: 50,
        flexDirection: 'row',
        justifyContent: 'space-around',
        borderWidth: 1,
        borderTopWidth: 0,
        borderLeftWidth: 0,
        borderRightWidth: 0,
        borderColor: '#ccc',
    },
});

area.json
式样

[
  {
    "value": "110000000000",
    "children": [
      {
        "value": "110100000000",
        "children": [
          {
            "value": "110101000000",
            "label": "东城区"
          },
          {
            "value": "110102000000",
            "label": "西城区"
          },
          {
            "value": "110105000000",
            "label": "朝阳区"
          },
          {
            "value": "110106000000",
            "label": "丰台区"
          },
          {
            "value": "110107000000",
            "label": "石景山区"
          },
          {
            "value": "110108000000",
            "label": "海淀区"
          },
          {
            "value": "110109000000",
            "label": "门头沟区"
          },
          {
            "value": "110111000000",
            "label": "房山区"
          },
          {
            "value": "110112000000",
            "label": "通州区"
          },
          {
            "value": "110113000000",
            "label": "顺义区"
          },
          {
            "value": "110114000000",
            "label": "昌平区"
          },
          {
            "value": "110115000000",
            "label": "大兴区"
          },
          {
            "value": "110116000000",
            "label": "怀柔区"
          },
          {
            "value": "110117000000",
            "label": "平谷区"
          },
          {
            "value": "110118000000",
            "label": "密云区"
          },
          {
            "value": "110119000000",
            "label": "延庆区"
          }
        ],
        "label": "北京市"
      }
    ],
    "label": "北京市"
  }
]
example_1.png
example_2.png
example_3.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,651评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,468评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,931评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,218评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,234评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,198评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,084评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,926评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,341评论 1 311
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,563评论 2 333
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,731评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,430评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,036评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,676评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,829评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,743评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,629评论 2 354