移动端省市区级联选择器

所属分类:输入-选择框

 4197  33  查看评论 (3)
移动端省市区级联选择器 ie兼容10

前言

最近在做移动端项目的时候遇到了省市区选择的功能。以往做项目时都是省市区分开的下拉框样式。这次希望实现效果图要求的级联选择器。我是 Framework7 框架的忠实粉丝,庆幸的是 Framework7 已经有模拟 iOS 选择框效果的 Picker 组件。在开发之前我先搜索了现有的一些选择器插件,整体而言都能满足需求但都不完美,比如滑动不流畅、显示有 Bug 等等。

Picker 级联选择器

基于 Framework7 制作级联选择器比较简单,关键是生成省市区数组以及省市区之间的联动。

以下是 CityPicker 的基本参数设置:

var pickerLocation = myApp.picker({
    input: '#location',//选择器
    rotateEffect: true,//设置旋转效果
    toolbarTemplate: '',//自定义按钮
    cols: [{
            cssClass: 'f-s-14',//添加自定义类
            width: 100,//列宽
            textAlign: 'left',//对齐方式
            values: province,//省数组
            onChange: function(picker, province) {//联动方法

            }
        },
        {
            cssClass: 'f-s-14',//添加自定义类
            width: 100,//列宽
            textAlign: 'center',//对齐方式
            values: city,//市数组
            onChange: function(picker, city) {//联动方法

            }
        },
        {
            cssClass: 'f-s-14',//添加自定义类
            width: 100,//列宽
            textAlign: 'right',//对齐方式
            values: area,//区数组
        }
    ]
});

其中省市区的格式都是基本数组,所以必须循环省市区数据生成相应的数组或者数据本身具有可以直接获取数组的结构。

province = ['北京','天津','河北','山东',...]
city = ['济南','青岛','淄博','滨州',...]
area = ['滨城区','惠民县','阳信县','博兴县',...]

省市区数据结构

没有想到一个简单的问题,最后竟然扯到了数据结构。经过尝试和思考,最终出现了三种数据结构,而这些东西应该都不是新鲜事。鉴于学识有限,我只能浅尝辄止的对比三者的异同,以及给出自己循环数据的方法。

1.无子父级关系的数组

去年做项目时省市区数据并没有从接口读取,而是保存到一个 JS 文件中。以下是后台从数据库导出的原始省市区数据片段(2016 年的数据,应该比较全,我删除了香港、澳门及台湾)。

[
    {
      "region_id": 11,
      "region_name": "北京市",
      "region_sort": 1,
      "region_remark": "直辖市",
      "pinyin": "beijingshi",
      "py": "bjs",
      "area_code": "110000",
      "parent_id": 1,
      "level": 1
    },
    {
      "region_id": 12,
      "region_name": "天津市",
      "region_sort": 2,
      "region_remark": "直辖市",
      "pinyin": "tianjinshi",
      "py": "tjs",
      "area_code": "120000",
      "parent_id": 1,
      "level": 1
    },
    {
      "region_id": 13,
      "region_name": "河北省",
      "region_sort": 3,
      "region_remark": "省份",
      "pinyin": "hebeisheng",
      "py": "hbs",
      "area_code": "130000",
      "parent_id": 1,
      "level": 1
    },
    ...
    {
      "region_id": 101,
      "region_name": "北京市",
      "region_sort": 1,
      "region_remark": null,
      "pinyin": "beijingshi",
      "py": "bjs",
      "area_code": "110100",
      "parent_id": 11,
      "level": 2
    },
    {
      "region_id": 102,
      "region_name": "天津市",
      "region_sort": 2,
      "region_remark": null,
      "pinyin": "tianjinshi",
      "py": "tjs",
      "area_code": "120100",
      "parent_id": 12,
      "level": 2
    },
    {
      "region_id": 105,
      "region_name": "邯郸市",
      "region_sort": 5,
      "region_remark": null,
      "pinyin": "handanshi",
      "py": "hds",
      "area_code": "130400",
      "parent_id": 13,
      "level": 2
    },
    ...
  }
]

 这个数据并没有明确的子父级关系,只能通过 parent_id 查找对应的省市。循环方式如下:

/**
 * [getProvince 获取省]
 * @param  {[Object]} regions [省市区数据]
 * @return {[Array]}          [省数组]
 */
function getProvince(regions) {

    $.each(regions, function() {
        if (this.level === 1) {
            province.push(this.region_name);
        }
    });

    return province;
}

/**
 * [getCity 获取市]
 * @param  {[Object]} regions      [省市区数据]
 * @param  {[String]} provinceName [省名]
 * @return {[Array]}               [市数组]
 */
function getCity(regions, provinceName) {

    var province_id = 0,
        cityArr = [];

    $.each(regions, function() {
        if (this.level === 1 && this.region_name === provinceName) {
            province_id = this.region_id;
            return false;
        }
    });
    $.each(regions, function() {
        if (this.level === 2 && this.parent_id === province_id) {
            cityArr.push(this.region_name)
        }
    });

    return cityArr;
}

/**
 * [getArea 获取区]
 * @param  {[Object]} regions      [省市区数据]
 * @param  {[String]} provinceName [省名]
 * @param  {[String]} cityName     [市名]
 * @return {[Array]}               [区数组]
 */
function getArea(regions, provinceName, cityName) {

    var province_id = 0,
        city_id = 0,
        areaArr = [];

    $.each(regions, function() {
        if (this.level === 1 && this.region_name === provinceName) {
            province_id = this.region_id;
        }
        if (this.level === 2 && this.region_name === cityName && this.parent_id === province_id) {
            city_id = this.region_id;
            return false;
        }
    });
    $.each(regions, function() {
        if (this.level === 3 && this.parent_id === city_id) {
            areaArr.push(this.region_name)
        }
    });

    return areaArr;
}

更多方法请参考

http://www.cnblogs.com/nzbin/p/7754447.html
相关插件-选择框

jQeruy年月日选择三级联动

使用标签创建选择年月日下拉框
  选择框
 4362  23

jquery数值范围选择插件jquery rangeslider

jquery rangeslider数值范围选择插件,鼠标拖动选择数值范围,提供三种风格样式
  选择框
 22573  69

9款表单复选框(Checkbox)与单选按钮美化

9款表单复选框(Checkbox)与单选按钮美化
  选择框
 9046  53

简单的jQuery多选下拉框

单纯的写了一个 平常用到的下拉框
  选择框
 4103  15

讨论这个项目(3)回答他人问题或分享插件使用方法奖励jQ币

    雨田君 0
    2017/11/10 12:20:06

    每次滑动都会获得值?

        nzb3290
        2017/11/10 18:04:43

        是啊

    回复
    胡亚倩 0
    2017/11/7 14:23:24
取消回复