适应移动端的地址四级(省市区街道)联动选择

首先推荐两款个人比较优秀的控件:

一、https://huangchanghuan.github.io/city-picker/  

这个是由 city-picker 控件(npm 安装方法: npm install city-picker),地址三级改造而来,数据由京东数据库提供。

优点:

1. 样式比较容易自定义;

2. 对省级地址按字母进行了区分,直观了然。

缺点:

1. 储存地址数据的文件,省市区街道四级在一个文件里,该文件接近 1M ,比较耗费流量;

2. 数据是由京东数据库提供,如果京东的地址数据库有更改,还需要手动进行更新。

二、http://jquerywidget.com/jquery-citys/

该地址数据库来源 http://passer-by.com/data_location/list.json ,由统计局最新数据同步。

优点:

1. 地址数据更新容易,能获取到统计局的最新数据;

2. 街道地址异步调用,根据不同的三级(区县)分为了多个 json 文件,文件较小。

缺点:

1. 默认样式比较适合电脑端,移动端需要更改 select 和 option 标签为其他标签(如:ul li),样式难以调整;

2. 需要更改源 js 文件比较多。

最近开发的项目中就是使用的第二个控件,来做的调整,项目运行在微信公众号中。下面详细介绍下步骤和源码分析

源码下载和介绍地址:https://github.com/xinjie-just/address-select.git

演示地址

效果图在 iPhone6 模拟机下演示:

图1. 初始化页面,未打开地址选择器时:

图2:地址选择器打开,待选择省级时:

 图三:街道地址加载中:

图四:回显

 源码分析:

<label for="Addr" id="areaLabel" class="address">
    <span>所在地区</span>
    <input type="text" name="Addr" id="Addr" readonly placeholder="请选择地区">
</label>
<div id="addressSelectWrapper">
    <div id="addressSelect">
        <div class="tip">
            <h3>所在地区</h3>
            <button type="button" id="cancel"></button>
        </div>
        <div id="address">
            <ul class="selected-address">
                <li class="lastarea" id="lastprovince">请选择</li>
                <li class="lastarea" id="lastcity">请选择</li>
                <li class="lastarea" id="lastarea">请选择</li>
                <li class="lastarea" id="lasttown">请选择</li>
            </ul>
            <div class="address-content">
                <ul id="province"></ul>
                <ul id="city"></ul>
                <ul id="area"></ul>
                <ul id="town"></ul>
            </div>
        </div>
    </div>
</div>
1. label#areaLabel 是用来显示地址和打开地址选择器的标签。
2. div#addressSelectWrapper 是用来存放整个地址选择器的容器。
3. div#addressSelect 是用来选择地址的容器,占 div#addressSelectWrapper 高度比例 70%。
4. div.tip 作为标题提示,包含有关闭按钮。
5. ul.selected-address 作为待选择地址提示和回显地址的列表
6. div.address-content 全部地址以及异步调用的街道地址的显示容器。

根据后期的优化和踩过的坑,对 js 源码部分解释:

一、在数据处理的市级数据处理时,如果按照以下选择会出现 bug

1. 选择直辖市 -> 2. 重新选择非直辖市的省级 -> 3. 选择任意一个城市

这种情况下,选择任意一个城市,它下面的区县级地址都是第一个城市的区县地址。

例如:

1. 选择北京市 -> 2. 重新选择四川省 -> 3. 选择四川省下的任意一个城市

它下面的区县都是第一个城市"成都"的区县

自贡市下面本该有自流井区、贡井区等,结果出现了成都市(排在第一位置的城市)的锦江区,青羊区等。

出现这个 bug 原因是选择直辖市后,在选择其它非直辖市的省级,没有重置 hasCity 的值,使其变为非直辖市。 hasCity = true 

//市级数据处理
city: function () {

    try {
        toolHanlder.showContent(2);
        toolHanlder.showLoading();
        toolHanlder.createHtml(2);

        //由于存在直辖市的问题,所以这里需要对市区进行特殊处理
        var len = $city.find("li").length;
        if (!len) {
            hasCity = false;
            $lastCity.hide();
            $city.hide();
            dataHanlder.area();
        } else {
            hasCity = true;   // 重置,使它表示非直辖市。否者如果先点击直辖市后,这里的值会是先前点击的直辖市,即 hasCity = false;
            // 选择城市
            $city.find("li")
                .click(function() {
                    var $this = $(this);
                    toolHanlder.liClick($this, 2);
                });
        }
    } catch (e) {
        console.log(e.message);
    } finally {
        toolHanlder.hideLoading();
    }

},

二、显示动画

在选择区县级地址后,将会调用该区县下的街道地址,如果网络慢的原因将会导致加载时间过长,中间有一些停顿的时间用户不知道接下来的操作流程。

//显示加载动画
showLoading: function() {
    $container.find("div.address-content").append('<div class="loading">加载中</div>');
},
//隐藏加载动画
hideLoading: function() {
    $container.find("div.loading").remove();
},

在每一级数据处理中,都去调用该方法显示加载动画,待数据加载完成后再隐藏加载动画。

三、为当前待地址特殊标记

给“作为待选择地址提示和回显地址的列表项 li.lastarea ”添加 active 类

//显示地区选择区域
showContent: function(level) {
    //显示对应的区域选择框

    //先移除所有的选择效果
    $lastProvince.siblings().addBack().removeClass('active');   // lxj, 上次成功选择的省级区域,去除同级别的li的样式
    $province.siblings().addBack().hide();    // lxj, 当前的省级选择,将同级别的影藏

    switch (level) {
    case 1:
        {
            $lastProvince.addClass('active').show();
            $province.show();
        }
        break;
    case 2:
        {
            $lastCity.addClass('active').show();
            $city.show();
        }
        break;
    case 3:
        {
            $lastArea.addClass('active').show();
            $area.show();
        }
        break;
    case 4:
        {
            $lastTown.addClass('active').show();
            $town.show();
        }
        break;
    }
},

如“显示地址选择区域”中,在每一级待要选择的地址中添加 active 类  $lastCity.addClass('active') 

更多说明及解释,查看 https://github.com/xinjie-just/address-select.git README.md。

原文地址:https://www.cnblogs.com/xinjie-just/p/7444361.html