• 移动端纯原生JS不依赖ajax后台服务器实现省市县三级联动


    最近好多天没有更新文章,是因为公司的项目忙的不行。今天有点时间,就突然想起在移动端项目中遇到三级联动的问题,网上查了很多资料,都是依赖各种插件,或者晦涩难于理解。于是,自己决定写一个出来。 当然,没有用到别的插件类库,也没有用ajax。写完这个小demo也学到不少,现在分享给大家代码。因为代码较多,我就不一个个解释了,源码里面添加了很多注释。 为了便于大家使用,我将html精简了许多。

    结尾会有在线运行地址。  

    0 <!DOCTYPE html>
    1 <html lang="en">
    2 <head>
    3 <meta charset="UTF-8">
    4 <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
    5     <meta name="apple-mobile-web-app-capable" content="yes">
    6 <title>三级联动</title>
    7 <link rel="stylesheet" href="index.css">
    8 </head>
    9 <body>
    10 <div class="select">
    11 请选择区域
    12 </div>
    13 <script src="city.js"></script>
    14 <script src="index.js"></script>
    15 </body>
    16 </html>

    至于三级联动的数据,我重新定义了一个js文件,在文件中创建了一个json对象,复制了服务器的三级联动的数据过来。 下面是javascript代码  

    0 (function(){
    1  
    2 var sel = document.querySelector('.select'),
    3 createDivFlag = true;
    4 windowHeight = window.screen.availHeight,
    5 startYFlag = 0;
    6  
    7 var div,cur,province,city,county,ok,resut,oneNum,twoNum,threeNum,touchFlag,
    8 touchOn = true,
    9 touchStop = true,
    10 tochBegin = true;
    11  
    12 //判断是否能打开
    13 sel.addEventListener('touchend',function(){
    14  
    15 createDivFlag && createDiv();
    16  
    17 })
    18  
    19 //开始生成盒子
    20 function createDiv(){
    21  
    22 //判断避免重复生成
    23 if(!div){
    24 div = document.createElement('div'),
    25 cur = document.createElement('div'),
    26 ok = document.createElement('div'),
    27 resut = document.createElement('div'),
    28 province = document.createElement('div'),
    29 city = document.createElement('div'),
    30 county = document.createElement('div');
    31  
    32 div.className = 'win';
    33 cur.className = 'current';
    34 ok.className = 'ok';
    35 resut.className = 'resut';
    36 province.className = 'province';
    37 city.className = 'city';
    38 county.className = 'county';
    39  
    40 ok.innerHTML = '完成';
    41 resut.innerHTML = '取消';
    42  
    43 //赋值translate
    44 province.style.transform = 'translateY(80px)';
    45 city.style.transform = 'translateY(80px)';
    46 county.style.transform = 'translateY(80px)';
    47 //给三个盒子绑定滑动事件
    48 touchGo([province,city,county]);
    49 div.appendChild(cur);
    50 div.appendChild(ok);
    51 div.appendChild(resut);
    52 div.appendChild(province);
    53 div.appendChild(city);
    54 div.appendChild(county);
    55 document.body.appendChild(div);
    56 }
    57  
    58  
    59 //填充数据
    60 fillIn(province,city,county);
    61  
    62  
    63 setTimeout(function(){
    64 div.style.transform = 'translateY(-200px)';
    65 },0);
    66  
    67 //确认选择
    68 ok.addEventListener('touchend',function(){
    69  
    70 var one = province.querySelectorAll('span')[oneNum],
    71 two = city.querySelectorAll('span')[twoNum] || null,
    72 three = county.querySelectorAll('span')[threeNum] || null,
    73 selId,
    74 oneHtml,
    75 twoHtml,
    76 threeHtml;
    77  
    78 oneHtml = one.innerHTML || '';
    79 twoHtml = two ? two.innerHTML : '';
    80 threeHtml = three ? three.innerHTML : '';
    81  
    82 sel.innerHTML = oneHtml + twoHtml + threeHtml;
    83  
    84  
    85 oneNodeValue = one ? one.attributes['data-id'].nodeValue : '';
    86 twoNodeValue = two ? two.attributes['data-id'].nodeValue : '';
    87 threeNodeValue = three ? three.attributes['data-id'].nodeValue : '';
    88 selId = oneNodeValue + twoNodeValue + threeNodeValue + '';
    89  
    90 sel.setAttribute('data-id',selId);
    91  
    92 div.style.transform = 'translateY(0)';
    93  
    94 createDivFlag = true;
    95  
    96 })
    97  
    98 //取消选择
    99 resut.addEventListener('touchend',function(){
    100  
    101 div.style.transform = 'translateY(0)';
    102  
    103 createDivFlag = true;
    104  
    105 })
    106  
    107 createDivFlag = false;
    108  
    109 }
    110  
    111  
    112  
    113 //给三级菜单填充内容
    114 function fillIn(province,city,county){
    115 var proStart,cityStart;
    116  
    117 //先将内容清空,避免后面累加
    118 province.innerHTML = '';
    119 city.innerHTML = '';
    120 county.innerHTML = '';
    121  
    122 //初始化位置
    123 for(k in region.p['000000']){
    124 var span = document.createElement('span');
    125 span.setAttribute("data-id",k);
    126 span.innerHTML = region.p['000000'][k];
    127 province.appendChild(span);
    128 }
    129  
    130 proStart = province.querySelector('span').attributes['data-id'].nodeValue;
    131  
    132 cityBegin(proStart,city);
    133  
    134 cityStart = city.querySelector('span').attributes['data-id'].nodeValue;
    135  
    136 countyBegin(cityStart,county);
    137  
    138 //初始化时自动先获取一遍初始值
    139 for(var i = 0; i < arguments.length; i += 1){
    140  
    141 //判断第二次打开,是否需要渲染二三级
    142 if(arguments[i].querySelector('span')){
    143  
    144 selectCity(arguments[i]);
    145  
    146 }
    147 }
    148  
    149 }
    150  
    151 //二级内容
    152 function cityBegin(proStart,city){
    153 var flag = true;
    154  
    155 if(region.c[proStart]){
    156  
    157 for(n in region.c[proStart]){
    158 var span = document.createElement('span');
    159 span.setAttribute('data-id',n);
    160 span.innerHTML = region.c[proStart][n];
    161 city.appendChild(span);
    162 }
    163  
    164 }else{
    165 flag = false;
    166 }
    167  
    168 return flag;
    169  
    170 }
    171  
    172  
    173 //三级内容
    174 function countyBegin(cityStart,county){
    175 for(j in region.d[cityStart]){
    176 var span = document.createElement('span');
    177 span.setAttribute('data-id',j);
    178 span.innerHTML = region.d[cityStart][j];
    179 county.appendChild(span);
    180 }
    181 }
    182  
    183  
    184 //为三级菜单绑定拓展事件
    185 function touchGo(objArr){
    186  
    187 for(var i = 0; i < objArr.length; i += 1){
    188  
    189 actionSwiper(objArr[i]);
    190  
    191 }
    192  
    193 //为三级菜单绑定事件
    194 function actionSwiper(obj){
    195  
    196 var startPosition,movePosition,endPosition,deletaY,transY;
    197  
    198 //tochBegin,touchOn,touchStop;三个状态判断
    199 obj.addEventListener('touchstart',function(event){
    200 if(touchStop){
    201 touchStop = false;
    202 var touch = event.touches[0];
    203 startPosition = {
    204 x : touch.pageX,
    205 y : touch.pageY
    206 }
    207 transY = Number(translateXY(obj));
    208 objHeight = obj.offsetHeight;
    209 tochBegin = true;
    210 }
    211  
    212 })
    213  
    214  
    215 //80 为两个span的高度,初始化时,距离上方80px
    216 //200 为自定义select的高度。
    217 obj.addEventListener('touchmove',function(event){
    218  
    219 if(tochBegin){
    220  
    221 touchOn = true;
    222  
    223 var touch = event.touches[0];
    224  
    225 movePosition = {
    226 x : touch.pageX,
    227 y : touch.pageY
    228 };
    229  
    230 deletaY = movePosition.y - startPosition.y + transY;
    231  
    232 //向上划上限
    233 //deletaY = deletaY > -objHeight - 80 + 200 ? deletaY : -objHeight - 80 + 200;
    234 deletaY = deletaY > -objHeight + 120 ? deletaY : -objHeight + 120;
    235  
    236 //向下滑下限
    237 deletaY = deletaY > 80 ? 80 : deletaY;
    238  
    239  
    240 obj.style.transform = 'translateY('+ deletaY +'px)';
    241  
    242 //禁止浏览器默认黑色背景出现
    243 event.preventDefault();
    244  
    245  
    246 }
    247  
    248 })
    249  
    250 obj.addEventListener('touchend',function(){
    251  
    252 if(touchOn){
    253  
    254 touchStop = true;
    255  
    256 var touch = event.changedTouches[0];
    257  
    258 endPosition = {
    259 x : touch.pageX,
    260 y : touch.pageY
    261 };
    262  
    263 setTimeout(function(){
    264 objTouchEnd(obj);
    265 },100);
    266  
    267 }
    268  
    269 })
    270  
    271 //滑动结束后处理函数
    272 function objTouchEnd(obj){
    273  
    274 var objTranslateY = parseInt(Number(translateXY(obj))),
    275 objType = '',
    276 timer = null;
    277  
    278 if(endPosition.y - startPosition.y > 0){
    279 objType = 'down';
    280 }else{
    281 objType = 'up';
    282 }
    283  
    284 timer = setInterval(function(){
    285  
    286  
    287 if(objType == 'up'){
    288 if(Number(translateXY(obj)) % 40 != 0){
    289 objTranslateY -= 1;
    290 }
    291 }
    292  
    293 if(objType == 'down'){
    294 if(Number(translateXY(obj)) % 40 != 0){
    295 objTranslateY += 1;
    296 }
    297 }
    298  
    299 obj.style.transform = 'translateY('+ objTranslateY +'px)';
    300  
    301 if(Number(translateXY(obj)) % 40 == 0){
    302  
    303 clearInterval(timer);
    304 timer = null;
    305  
    306 tochBegin = false;
    307  
    308 //确定选择
    309 selectCity(obj);
    310  
    311 }
    312  
    313  
    314 },20);
    315  
    316  
    317  
    318 }
    319  
    320 }
    321  
    322 }
    323  
    324  
    325 //获取设置选项
    326 function selectCity(obj){
    327 //80+80=160   Y为80 的时候是第一个
    328 var objTranslateY = Number(translateXY(obj)),
    329 one,
    330 oneId,
    331 onText,
    332 two,
    333 twoId,
    334 twoText,
    335 three,
    336 threeId,
    337 threeText,
    338 twoGoThree;
    339  
    340 if(obj == province){
    341  
    342 oneNum =  Math.abs((objTranslateY + 80 - 160) / 40);
    343  
    344 //获取序号
    345 one = province.querySelectorAll('span')[oneNum];
    346  
    347 //获取自定义属性值
    348 oneId = one.attributes['data-id'].nodeValue;
    349  
    350 //清空下一级内容
    351 city.innerHTML = '';
    352  
    353 //重置下一级translateY
    354 city.style.transform = 'translateY(80px)';
    355  
    356 //重置第三级translateY
    357 county.style.transform = 'translateY(80px)';
    358  
    359 //填充下一级内容
    360 twoGoThree = cityBegin(oneId,city);
    361  
    362 //清空第三项
    363 county.innerHTML = '';
    364  
    365 //默认第三级默认第二级第一项
    366 if(twoGoThree){
    367 countyBegin(city.querySelector('span').attributes['data-id'].nodeValue,county);
    368 }
    369  
    370 }
    371  
    372 if(obj == city){
    373  
    374 twoNum =  Math.abs((objTranslateY + 80 - 160) / 40);
    375  
    376 //获取序号
    377 two = city.querySelectorAll('span')[twoNum];
    378  
    379 //获取选中选项自定义属性值
    380 twoId = two.attributes['data-id'].nodeValue;
    381  
    382 //清空第三项值
    383 county.innerHTML = '';
    384  
    385 //重置第三项translateY
    386 county.style.transform = 'translateY(80px)';
    387  
    388 //填充第三项
    389 if(twoId){
    390 countyBegin(twoId,county);
    391 }
    392  
    393 }
    394  
    395 if(obj == county){
    396  
    397 threeNum =  Math.abs((objTranslateY + 80 - 160) / 40);
    398  
    399 //获取序号
    400 three = county.querySelectorAll('span')[threeNum];
    401  
    402 //获取选中选项自定义属性值
    403 threeId = three.attributes['data-id'].nodeValue;
    404  
    405 }
    406  
    407 }
    408  
    409 //获取translateY值
    410 function translateXY(obj){
    411     var beeTransform = obj.style.transform.replace(/s/g,'');
    412     beeTransform = beeTransform.replace('translateY','');
    413     beeTransform = beeTransform.slice(1,-1);
    414     beeTransform = beeTransform.replace('px','');
    415     return beeTransform;
    416 }
    417  
    418 })()

    在线运行   在线运行请在谷歌浏览器调试模式下模拟手机环境运行。暂未进行仔细测试,如有问题,欢迎留言共同探讨。

    原文链接-摘自大公爵ddamy.com

  • 相关阅读:
    prepareStatement的用法和解释
    java socket报文通信(一) socket的建立
    java多线程小结
    Java_XML操作
    socket实例2
    socket实例1
    Socket小结
    从源码角度理解android动画Interpolator类的使用
    android使用属性动画代替补间动画
    OKHttp的简单使用
  • 原文地址:https://www.cnblogs.com/webhb/p/5755697.html
Copyright © 2020-2023  润新知