先睹为快

闲话少说,我们先来看看今天我们研究的控件的最终效果图(参照天猫的送货地址设置的效果):

“地址选择Web控件”的基本组成:

使用控件举例:

复制代码
<!--需要加载和引用的文件-->
<link rel="stylesheet" href="css/zlbox.css" type="text/css" media="screen" />
<script src="js/jquery-1.7.1.js"></script>
<script src="js/jquery.zlbox.js"></script>

<!--控件的HTML代码-->
<div id="company_addr" class="zl_addressbox">
           <div class="ab_showbar tip">
              <div class="tip_info">请选择省市区</div>
              <div class="value_info">
                  <!--结果显示容器-->
              </div>
           </div>
           <span class="ab_btn"></span>
           <div class="selectaddr_box">
              <div class="ab_bar">
                 <ul>
                    <li class="sheng current">省份</li>
                    <li class="shi">城市</li>
                    <li class="qu">区县</li>
                 </ul>
              </div>
              <div class="ab_panel">
                <dl>
                   <dd class="sheng current">
                      <div class="ab_group">
                        <span class="ab_shengtitle">A-G</span>
                        <ul class="ab_sheng ab_item">
                           <li>北京</li>
                           <li>广东</li>
                        </ul>
                      </div>
                      <div class="ab_group">
                        <span class="ab_shengtitle">T-Z</span>
                        <ul class="ab_sheng ab_item">
                           <li>浙江</li>
                        </ul>
                      </div>
                   </dd>
                   <dd class="shi">
                      <ul class="ab_shi ab_item">
                        <!--市区容器-->
                      </ul>
                   </dd>
                   <dd class="qu">
                      <ul class="ab_qu ab_item">
                        <!--区县容器-->
                      </ul>
                   </dd>
                </dl>
              </div>
           </div>
        </div>
        <!--End of ZLAddressBox-->


<script type="text/javascript">
    //初始化地址控件
    $(\'#company_addr\').czl_addressbox({});
</script>
复制代码

 

为了讲解的方便,控制代码的篇幅,这里仅仅举例了北京、广东、浙江3个省市的“省份/城市/区县”选择,数据完整的“全国地址选择Web控件”还在捣鼓中,出货后再向诸位汇报。

基本功能实现

【HTML代码】

Web控件涉及的HTML代码如下:

复制代码
<!--ZLAddressBox-->
        <div id="company_addr" class="zl_addressbox">
           <div class="ab_showbar tip">
              <div class="tip_info">请选择省市区</div>
              <div class="value_info">
                  <!--结果显示容器-->
              </div>
           </div>
           <span class="ab_btn"></span>
           <div class="selectaddr_box">
              <div class="ab_bar">
                 <ul>
                    <li class="sheng current">省份</li>
                    <li class="shi">城市</li>
                    <li class="qu">区县</li>
                 </ul>
              </div>
              <div class="ab_panel">
                <dl>
                   <dd class="sheng current">
                      <div class="ab_group">
                        <span class="ab_shengtitle">A-G</span>
                        <ul class="ab_sheng ab_item">
                           <li>北京</li>
                           <li>广东</li>
                        </ul>
                      </div>
                      <div class="ab_group">
                        <span class="ab_shengtitle">T-Z</span>
                        <ul class="ab_sheng ab_item">
                           <li>浙江</li>
                        </ul>
                      </div>
                   </dd>
                   <dd class="shi">
                      <ul class="ab_shi ab_item">
                        <!--市区容器-->
                      </ul>
                   </dd>
                   <dd class="qu">
                      <ul class="ab_qu ab_item">
                        <!--区县容器-->
                      </ul>
                   </dd>
                </dl>
              </div>
           </div>
        </div>
        <!--End of ZLAddressBox-->
复制代码

【CSS代码】

Web控件涉及到的CSS代码(zlbox.css)如下:

复制代码
  1 /**全国地址选择控件**/
  2 .zl_addressbox{
  3     position:relative;
  4     width:370px;
  5     background-color:#F08;
  6 }
  7 .zl_addressbox .ab_showbar{
  8     width:100%;
  9     height:30px;
 10     line-height:30px;
 11     border:#A9A9A9 1px solid;
 12     background-color:#FFF;    
 13 }
 14 .zl_addressbox .ab_btn{
 15     position:absolute;
 16     right:0px;
 17     top:1px;
 18     width:30px;
 19     height:30px;
 20     background:#FFF url(\'img/cb_btn_down.png\') no-repeat center center;
 21 }
 22 /**地址选择面板**/
 23 .zl_addressbox .selectaddr_box{
 24     display:none;
 25     position:absolute;
 26     left:0px;
 27     right:0px;
 28     top:32px;
 29     width:100%;
 30     line-height:30px;
 31     background-color:#FFF;
 32     z-index:888;
 33 }
 34 .zl_addressbox .ab_bar{
 35     width:100%;
 36     height:40px;
 37 }
 38 .zl_addressbox .ab_bar:after{
 39     clear:both;
 40     content:\'\';
 41     display:table;
 42 }
 43 .zl_addressbox .ab_bar li{
 44     float:left;
 45     width:122px;     /**这里如果要调整容器大小,需要同步调整**/
 46     height:40px;
 47     line-height:40px;
 48     text-align:center;
 49     background-color:#F0F0F0;
 50     border-left:#CCC 1px solid;
 51     border-bottom:transparent 1px solid ;
 52     cursor:pointer;
 53 }
 54 .zl_addressbox .ab_bar li:first-child{
 55     border-left:none;
 56 }
 57 .zl_addressbox .ab_bar li.current{
 58     color:#009AFD;
 59     background-color:#FFF;
 60     cursor:none;
 61 }
 62 .zl_addressbox .ab_panel{
 63     position:relative;
 64     width:100%;
 65 }
 66 .zl_addressbox .ab_panel dd{
 67     display:none;
 68     position:relative;
 69     width:100%;
 70 }
 71 .zl_addressbox .ab_panel dd.current{
 72     display:block;
 73 }
 74 /**省份面板中的分组**/
 75 .zl_addressbox .ab_panel dd .ab_group{
 76     position:relative;
 77     width:100%;
 78     margin-bottom:20px;
 79 }
 80 .zl_addressbox .ab_panel dd .ab_group span.ab_shengtitle{
 81     display:block;
 82     position:absolute;
 83     top:0px;
 84     width:60px;
 85     height:30px;
 86     line-height:30px;
 87     text-align:center;
 88     font-size:0.8em;
 89     color:#009AFD;
 90 }
 91 .zl_addressbox .ab_panel dd .ab_group .ab_sheng{
 92     margin-left:40px;
 93 }
 94 .zl_addressbox .ab_panel dd ul.ab_item{
 95     margin-top:10px;
 96     margin-bottom:5px;
 97 }
 98 .zl_addressbox .ab_panel dd ul.ab_item:after{
 99     clear:both;
100     display:table;
101     content:\'\';
102 }
103 .zl_addressbox .ab_panel dd ul.ab_item li{
104     float:left;
105     height:30px;
106     line-height:30px;
107     padding:0px 10px;
108     margin-left:10px;
109     cursor:pointer;
110 } 
111 .zl_addressbox .ab_panel dd ul.ab_item li:hover{
112     color:#009AFD;
113 }
114 .zl_addressbox .ab_panel dd ul.ab_item li.current{
115     border-radius:6px;
116     color:#FFF;
117     background-color:#009AFD;
118 }
119 .zl_addressbox.selected .selectaddr_box{
120     display:block;
121     border-left:1px #CCCCCC solid;
122     border-right:1px #CCCCCC solid;
123     border-bottom:1px #CCCCCC solid;
124     padding-bottom:10px;
125 }
126 .zl_addressbox.selected  .ab_btn{
127     background:#FFF url(\'img/cb_btn_up.png\') no-repeat center center;
128 }
129 /**提示状态**/
130 .zl_addressbox .ab_showbar .tip_info{
131     display:none;
132     width:90%;
133     padding-left:5px;
134     color:#CCCCCC;
135 }
136 .zl_addressbox .ab_showbar .value_info{
137     display:block;
138     width:90%;
139     padding-left:5px;
140 }
141 .zl_addressbox .ab_showbar .value_info span.sep{
142     color:#CCC;
143     font-size:0.8em;
144 }
145 
146 .zl_addressbox .ab_showbar.tip .value_info{
147     display:none;
148 }
149 .zl_addressbox .ab_showbar.tip .tip_info{
150     display:block;
151 }
复制代码

结合我们的功能诉求,一级前面介绍的控件的组成,将HTML代码与CSS代码对照起来理解应该比较好理解,所以,关于控件涉及到的布局、样式等细节,就不展开赘述,我们把重点放到JavaScript的代码部分。开发Web控件的基本套路与前一篇博文:ZLComboBox自定义控件开发详解  类似,本文就着重讲解控件的业务需求以及与ZLComboBox控件开发不一样的地方。

JavaScript–闭包实现

与ZLComboBox控件不同,本文我们采用闭包的方式来构建我们的控件对象,jQuery插件的基本代码如下:

复制代码
$.fn.czl_addressbox = function( options )
   {
       this.each( function()  
       {
          var instance = $.data( this , \'czl_addressbox\' );
          
          if( !instance )
          {
            $.data( this, \'czl_addressbox\' , $.createAddressBox( options , this ) );  
          
       });//end of each
       
       return this;  //支持链式操作
   };
复制代码

控件对象通过createAddressBox()来返回一个控件对象,下面我们重点来分析一下createAddressBox()的基本组成。

整个控件对象基于地址的\’三级\’目录树,以id来进行各级行政单位的标识与处理。

整个控件对外的接口:

   1> 创建控件时,可以传入一个对象字面量(options),用于设置默认选中的地址。

   2> 返回当前选中地址的对象字面量:get_addr_obj()。

   3> 传入一个地址对象字面量:set_addr_obj( new_addr_obj )。

 

业务流程分析:

1> 默认情况下,控件显示\’请选择省市区\’的提示信息。

2> 单击控件\’地址栏\’,显示下拉的\’地址选择面板\’;再次单击\’地址栏\’,隐藏下拉的\’地址选择面板\’;下拉的\’地址选择面板\’反映当前的选择状态。

3> 在\’省份\’面板中选中一个\’省级单位\’后,自动显示选中省级单位下的\’市级\’行政区。

     在\’城市\’面板中选中一个\’市级单位\’后,自动显示选中市级单位下的\’区级\’行政区。

     在\’区县\’面板中选中一个\’区级单位\’后,自动隐藏\’地址选择面板\’。

     所有的选择结果,都会实时在控件\’地址栏\’中显示出来。

4> 只有选中了\’省级\’单位之后,才能单击\’市级\’单位的页签,

     只有选中了\’市级\’单位之后,才能单击\’区级\’单位的页签。

5> 当更改了某一级别的选择结果之后,将它的下一级单位的选择清空。

     例如:已经选择了”广东/深圳”,这时候单击”省份”面板中的”浙江”,则原来”城市面板”中的内容被清空,重新设置为”浙江”所包含的城市。

 

综合业务需求,闭包中的成员可以包括:

私有属性

  • 保存了\’三级地址信息\’的对象字面量:addr_box_data
  • 用于记录选择结果的对象字面量:addr_obj
  • 一些HTML元素的引用等:例如;地址栏元素ab_showbar

私有函数

  •  选中某个\’省级单位\’,\’市级单位\’和\’区级单位\’之后的响应函数。

        _selectShengId( sheng_index )

        _selectShiId( shi_index )

        _selectQuId( qu_index )

  • 更新地址栏信息的函数:_updateAddrValue( )
  • 创建控件时,要执行的初始化函数:_init( options )
  • 相关控件的注册函数:_loadEvents( ),这个函数应该在_init()中被调用。

因为整个架构都是基于id来创建,而从界面呈现来看,我们更习惯于\’地址名称\’,

例如:”浙江省”的id是多少?不去翻阅addr_box_data,我们是回答不上来的。

所以,增加一个辅助函数:getShengIDFromName( sheng_name )

控件对外提供的接口函数

  • 获得当前选中的地址信息的对象字面量:get_addr_obj()
  • 设置默认选中的地址信息:set_addr_obj:function( a_obj )

控件提供的HTML接口

每次更新addr_obj的时候,同步将地址的信息更新到 HTML 元素的data属性中,名称为:addr_value。

例如:如果依次选中了:\’浙江>杭州>滨江\’,那么,addr_value的值为:\’浙江_杭州_滨江\’。

这种方式的好处是:在应用中直接用$(\’.zl_addressbox\’).czl_addressbox({}); 就把所有的addressbox控件都初始化了。后续要取值时,直接从对应元素的data属性中获取即可,而不用去分析如何调用控件对象。

综合以上分析,createAddressBox()代码的基本框架如下:

复制代码
$.createAddressBox = function( options , element ){
        //私有成员声明
        var addr_box = $( element );
        //相关的HTML组件
        //......
        
        //省份的选择控件
        var ab_sheng_item = addr_box.find( \'.ab_sheng>li\' );
        
        //保存了\'三级地址信息\'的对象字面量
        var addr_box_data = {} ;       
        
        //用于记录选择结果的对象字面量
               var addr_obj = {};
        
        //私有函数声明
        var _init = function( options ){
            //加载事件注册
            _loadEvents();

addr_box.data( \'addr_value\' , \'\' );
//...
        };
        
        //依据a_obj的值初始化控件的状态
        var _init_addr_obj = function( a_obj ){
            //......
        }
        
        //更新地址栏中的值
        var _updateAddrValue = function(){
            //......
        };
        
        //选择序号为sheng_id的省份之后的响应事件
        var _selectShengId = function( sheng_index ){
            //......
        };
        
        //选择序号为shi_index的城市之后的响应事件
        var _selectShiId = function( shi_index ){
             //......
        };
        //选择序号为qu_index的区县之后的响应事件
        var _selectQuId = function( qu_index ){
            //......
        };
        
        //根据省份的名称,选择对应的id
        var getShengIDFromName = function( sheng_name ){
            //......
        }
        
        //注册事件
        var _loadEvents = function(){
            //......    
        };

        //执行初始化函数
        _init( options );

        //创建对象
        var that = {
            get_addr_obj:function(){
                return addr_obj;
            },
            set_addr_obj:function( a_obj ){
                _init_addr_obj( a_obj );
                return ;
            }
        };
        
        
        //返回对象
        return that ;
   }        
复制代码

JavaScript–事件冒泡

重点看一下\’市级\’面板和\’区级\’面板相关选项的单击事件处理。根据前面的分析,我们发现这两个面板的选项,是动态变化的,那我们应该如何处理呢?

这让我们想到了事件的\’冒泡\’机制,只要注册相关容器的单击事件,当选中某个选项时,自然会冒泡到\’容器\’的处理函数那里。不难,直接上代码:

复制代码
        //注册事件
        var _loadEvents = function(){
            //......
        
            //单击\'市\'下面的选项的响应事件
            ab_shi_databox.on( \'click\' , function( event ){
                //阻止事件冒泡
                event.stopPropagation();
                var $target = $( event.target );
                if( $target.attr( \'tagName\' ) === \'li\' ){
                    var shi_item = $target ;
                    //如果当前的\'市\'选项就是选中的选项,则不响应事件,直接返回
                    if( shi_item.hasClass(\'current\') ){
                        return ;
                    }
                    //获得省份对应的id的值
                    var shi_id = shi_item.index();
                    //响应选中城市之后的响应函数
                    _selectShiId( shi_id );
                    //标记当前选中的"城市"
                    shi_item.addClass(\'current\').siblings().removeClass( \'current\' );
                }//如果是子元素li上触发的事件
                return ;
            });
            
            //单击\'区\'下面的选项的响应事件
            ab_qu_databox.on( \'click\' , function( event ){
                //阻止事件冒泡
                event.stopPropagation();
                var $target = $( event.target );
                if( $target.attr( \'tagName\' ) === \'li\' ){
                    var qu_item = $target ;
                    if( qu_item.hasClass(\'current\') ){
                        return ;
                    }
                    //获得省份对应的id的值
                    var qu_id = qu_item.index();
                    //响应选中城市之后的响应函数
                    _selectQuId( qu_id );
                    qu_item.addClass(\'current\').siblings().removeClass( \'current\' );
                    return ;
                }
            });
        
        };
                
复制代码

 

优化控件:

 到目前为止,我们的控件已经能够工作了,但是,还有一些可以优化地方,我们一起来分析一下。

JavaScript–单例模式

每次我们使用控件的时候,都要执行createAddressBox()创建一个对象,根据闭包的特性,每次创建时,闭包中的私有属性成员都会被单独创建,作为一个完整的工作区占据内存空间。 我们注意到包含”三级地址信息”的addr_box_data也是一个\’私有属性\’,而这个对象字面量所占的内存空间非常大,如果每次调用createAddressBox()都占用一段大内存空间,从性能上来看,显然不是一个好的设计。

因为addr_box_data的内容是固定的,所以,可以把”三级地址信息”保存到一个单独的全局空间中,

而仅仅在createAddressBox()中引用这个全局空间即可。

   优化方式如下:

   a. 创建一个全局变量:$.zl_addr_box_data。

   b. 在createAddressBox中引用这个全局变量。

相关的代码示例如下:

复制代码
$.createAddressBox = function( options , element ){
      //......
      var addr_box_data = $.zl_addr_box_data;         //引用的全局变量
      //......
}    


//保留有全国地址信息的全局变量
   $.zl_addr_box_data = (function( ){
      var that = {
\'0\':[\'北京\',\'浙江\',\'广东\'],
\'0_0\':[\'北京\'],
\'0_0_0\':[\'东城\',\'西城\',\'崇文\',\'宣武\',\'朝阳\',\'丰台\',\'石景山\',\'海淀\',\'门头沟\',\'房山\',\'通州\',\'顺义\',\'昌平\',\'大兴\',\'怀柔\',\'平谷\',\'密云\',\'延庆\'],
\'0_1\':[\'杭州\',\'宁波\',\'温州\',\'嘉兴\',\'湖州\',\'绍兴\',\'金华\',\'衢州\',\'舟山\',\'台州\',\'丽水\'],
\'0_1_0\':[\'上城\',\'下城\',\'江干\',\'拱墅\',\'西湖\',\'滨江\',\'萧山\',\'余杭\',\'桐庐\',\'淳安\',\'建德\',\'富阳\',\'临安\'],
\'0_1_1\':[\'海曙\',\'江东\',\'江北\',\'北仑\',\'镇海\',\'鄞州\',\'象山\',\'宁海\',\'余姚\',\'慈溪\',\'奉化\'],
\'0_1_2\':[\'鹿城\',\'龙湾\',\'瓯海\',\'洞头\',\'永嘉\',\'平阳\',\'苍南\',\'文成\',\'泰顺\',\'瑞安\',\'乐清\'],
\'0_1_3\':[\'秀城\',\'嘉善\',\'海盐\',\'海宁\',\'平湖\',\'桐乡\'],
\'0_1_4\':[\'吴兴\',\'南浔\',\'德清\',\'长兴\',\'安吉\'],
\'0_1_5\':[\'越城\',\'绍兴\',\'新昌\',\'诸暨\',\'上虞\',\'嵊州\'],
\'0_1_6\':[\'婺城\',\'金东\',\'武义\',\'浦江\',\'磐安\',\'兰溪\',\'义乌\',\'东阳\',\'永康\'],
\'0_1_7\':[\'柯城\',\'衢江\',\'常山\',\'开化\',\'龙游\',\'江山\'],
\'0_1_8\':[\'定海\',\'普陀\',\'岱山\',\'嵊泗\'],
\'0_1_9\':[\'椒江\',\'黄岩\',\'路桥\',\'玉环\',\'三门\',\'天台\',\'仙居\',\'温岭\',\'临海\'],
\'0_1_10\':[\'莲都\',\'青田\',\'缙云\',\'遂昌\',\'松阳\',\'云和\',\'庆元\',\'景宁\',\'龙泉\'],
\'0_2\':[\'广州\',\'韶关\',\'深圳\',\'珠海\',\'汕头\',\'佛山\',\'江门\',\'湛江\',\'茂名\',\'肇庆\',\'惠州\',\'梅州\',\'汕尾\',\'河源\',\'阳江\',\'清远\',\'东莞\',\'中山\',\'潮州\',\'揭阳\',\'云浮\'],
\'0_2_0\':[\'荔湾\',\'越秀\',\'海珠\',\'天河\',\'白云\',\'黄埔\',\'番禺\',\'花都\',\'南沙\',\'萝岗\',\'增城\',\'从化\'],
\'0_2_1\':[\'武江\',\'浈江\',\'曲江\',\'始兴\',\'仁化\',\'翁源\',\'乳源\',\'新丰\',\'乐昌\',\'南雄\'],
\'0_2_2\':[\'罗湖\',\'福田\',\'南山\',\'宝安\',\'龙岗\',\'盐田\',\'光明新区\',\'坪山新区\',\'龙华新区\',\'大鹏新区\'],
\'0_2_3\':[\'香洲\',\'斗门\',\'金湾\'],
\'0_2_4\':[\'龙湖\',\'金平\',\'濠江\',\'潮阳\',\'潮南\',\'澄海\',\'南澳\'],
\'0_2_5\':[\'禅城\',\'南海\',\'顺德\',\'三水\',\'高明\'],
\'0_2_6\':[\'蓬江\',\'江海\',\'新会\',\'台山\',\'开平\',\'鹤山\',\'恩平\'],
\'0_2_7\':[\'赤坎\',\'霞山\',\'坡头\',\'麻章\',\'遂溪\',\'徐闻\',\'廉江\',\'雷州\',\'吴川\'],
\'0_2_8\':[\'茂南\',\'茂港\',\'电白\',\'高州\',\'化州\',\'信宜\'],
\'0_2_9\':[\'端州\',\'鼎湖\',\'广宁\',\'怀集\',\'封开\',\'德庆\',\'高要\',\'四会\'],
\'0_2_10\':[\'惠城\',\'惠阳\',\'博罗\',\'惠东\',\'龙门\'],
\'0_2_11\':[\'梅江\',\'梅县\',\'大埔\',\'丰顺\',\'五华\',\'平远\',\'蕉岭\',\'兴宁\'],
\'0_2_12\':[\'城区\',\'海丰\',\'陆河\',\'陆丰\'],
\'0_2_13\':[\'源城\',\'紫金\',\'龙川\',\'连平\',\'和平\',\'东源\'],
\'0_2_14\':[\'江城\',\'阳西\',\'阳东\',\'阳春\'],
\'0_2_15\':[\'清城\',\'佛冈\',\'阳山\',\'连山\',\'连南\',\'清新\',\'英德\',\'连州\'],
\'0_2_16\':[\'东莞\'],
\'0_2_17\':[\'中山\'],
\'0_2_18\':[\'湘桥\',\'潮安\',\'饶平\'],
\'0_2_19\':[\'榕城\',\'揭东\',\'揭西\',\'惠来\',\'普宁\'],
\'0_2_20\':[\'云城\',\'新兴\',\'郁南\',\'云安\',\'罗定\'],
      };      
      return that ;
   })();
复制代码

 

特殊情况处理:

我们注意到,像北京、上海、天津这些直辖市,虽然是省级单位,但是它的下面直接就是包含了各个区的”区级单位”,为了保证\’三级地址结构\’的一致性,我们给它补上\’市级单位\’,名称也是北京市。但是,在用户选择的时候,如果还要按”北京 > 北京 > 海淀”这样的方式,就显得太麻烦了,所以,我们做如下的优化:

a. 当用户选中一个\’省级单位\’时,如果它下面只有一个\’市级单位\’,就直接跳过这个\’市级单位\’。

      比如:用户选中\’北京\’之后,就直接显示\’朝阳\’、\’海淀\’等\’区级单位\’

b. 优化显示结果:

      如果发现用户选中的\’省级单位\’与\’市级单位\’的名称一样,就只显示省级单位。

      例如:北京/石景山

优化的相关代码如下:

复制代码
   $.createAddressBox = function( options , element ){
             //......
             //选择序号为sheng_id的省份之后的响应事件
         var _selectShengId = function( sheng_index ){
                //......
                //判断是否是\'北京\'、\'上海\'、天津、重庆等直辖市
                var shi_list_id = \'0_\'+sheng_index;
                //这里处理需要跳过\'市\'这一级别的处理
                if( addr_box_data[shi_list_id].length === 1 ){
                    //更新地址的值
                    addr_obj.sheng = sheng_name;
                    addr_obj.shi = \'\' + addr_box_data[\'0_\'+sheng_index+\'_0\'] ;
                    addr_obj.qu = \'\' ;
                    addr_obj.sheng_id = \'\'+sheng_index;
                    addr_obj.shi_id = \'0\' ;
                    addr_obj.qu_id = \'\' ;
                                
                    //更新地址栏中的值
                    _updateAddrValue( );
                    //触发选中了区的选项卡
                    _selectShiId( 0 );
                }
               //......
        }

        //更新地址栏中的值
        var _updateAddrValue = function(){
              //......
                  if( addr_obj.shi !== \'\' &&  addr_obj.shi === addr_obj.sheng){
                    if( addr_obj.qu !== \'\' ){
                        ab_vauleinfo.append( \'<span class="sep">/</span><span>\'+addr_obj.qu+\'</span>\' );
                    }
} //...... } }
复制代码

小节:

本文所论述的是地址控件的业务原理,在真正的生产环境中使用时,也许还需要结合控件的使用场景,

公司的业务规范来进行优化,比如思考以下几个方面:

a. 安全性:我们当前的设计,是将\’三级地址信息\’直接放到JS脚本中,在实际的业务场景中,你或许需要将这个信息放到\’云端\’,用到时才从\’云端\’动态加载。

这样做的另外一个好处就是,当信息发生变化时(例如:行政区域发生变更),只要更新\’云端\’的数据就可以了。

b. 移动化:我们当前的设计,是将\’地址选择面板\’进行\’悬挂式\’设计,即:显示\’地址选择面板\’时,并不会影响原来的布局流。这个在某些使用场景时可能会出现问题,例如:如果这个控件放置在页面的底部,就不能完整的显示整个\’地址选择面板\’,这个在\’移动化\’应用设计中会遇到比较多,这时候,也许将它修改成\’抽屉式\’设计更合理一些。

\’悬挂式\’设计和\’抽屉式\’设计的示意图如下:

 

抽屉式\’设计的样式如何写?就留作练习,让大家练练手吧。

c. 兼容性:在前端设计中,因为您可能会遇到各种浏览器,所以兼容性也是需要大家考量的问题,例如事件的注册、事件对象访问等,不过由于我们采用了jQuery库,很多兼容性问题jQuery库已经帮我们解决了。

不提供源代码的控件分析都是耍流氓,单击\’这里\’,下载讲解的示例代码。

完整的全国\’三级地址\’,小生正在整理中,诸位大哥如果想要一起研究,共同完善,请留下邮箱,待小生整理完毕之后,会即时向诸位汇报。

感谢诸位捧场。

版权声明:本文为LiuJL原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/LiuJL/p/5416972.html