仿淘宝收货地址录入
淘宝收货地址需要通过下拉列表选择省、市、县、乡来设置,本文试用原生js实现,效果如图;

省、市、县、乡代码和名称列表在pcas-code.js文件,可以从网上下载,最新信息请看民政部网站;pcas-code.js定义一个json数组pcas,如图显示为河北省秦皇岛市北戴河区海滨镇;

代码如下:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title></title> <script src="js/pcas-code.js"></script> <style type="text/css"> *, :after, :before { box-sizing: border-box; color: #333; padding: 0px; margin: 0px; } .area-entrance { width: 427px; font-size: 12px; line-height: 1.6; } .area-header{ font-size: 0px; } .area-header-tips { display: inline-block; padding-right: 12px; color: #333; width: 78px; line-height: 30px; vertical-align:top; font-size: 12px; } .area-header-tips:before { margin-right: 4px; content: "*"; color: #ff3000; } .area-header-click { display: inline-block; position: relative; width: 336px; /*min-height: 28px;*/ /*vertical-align: middle;*/ line-height: 28px; padding: 0px 8px; border: 1px solid #CCCCCC; border-radius: 3px; } .area-header-click:hover { cursor: pointer; } .placeholder { color: #999; } .area-header-click-input{ display: inline-block; width: 318px; /*height: 28px;*/ line-height: 28px; vertical-align: top; font-size: 12px; /*overflow: visible;*/ min-height: 28px; } .area-input-name{ display: inline-block; margin: -2px 5px; overflow: hidden; vertical-align: top; } .area-input-symbol{ /*vertical-align: top;*/ } .area-header-click-icon { background: url(img/down.png) no-repeat center right; display: inline-block; width: 11px; height: 6px; position: absolute; top: 10px; right: 8px; } .area-box { display: none; border: 1px solid #CCCCCC; } .area-box-title ul { display: flex; list-style: none; padding: 0px; margin: 0px; height: 30px; border-bottom: 1px solid #ccc; } .area-box-title ul li { width: 25%; /*flex: 1;*/ float: left; height: 29px; line-height: 29px; text-align: center; background-color: #F0F0F0; } .area-box-title .area-box-title-current{ background-color: #FFF; } .area-box-title ul li:hover { cursor: pointer; } .area-box-content-panel { display: none; } .area-box-content-visible { display: block; } .area-box-content-panel ul { height: 320px; list-style: none; padding: 0px; overflow: auto; margin: 5px 10px; } .area-box-content-list li { padding: 10px 5px; } .area-box-content-list li:hover { color: #4a8cff; } .area-current { color: #4a8cff; font-weight: 700; } .area{ position: absolute; left: 300px; top: 100px; } </style> </head> <body> <div class="area"> <div class="area-entrance" id="area-entrance"> <div class="area-header"> <span class="area-header-tips"><label>地址信息:</label></span> <div class="area-header-click"><span class="area-header-click-input"> <span class="placeholder">请选择省/市/区/街道</span></span> <span class="area-header-click-icon"></span> </div> </div> <div class="area-box"> <div class="area-box-title" > <ul> <li>省</li> <li>市</li> <li>区</li> <li>街道</li> </ul> </div> <div class="area-box-content"> <div class="area-box-content-panel"> <ul class="area-box-content-list"> </ul> </div> <div class="area-box-content-panel"> <ul class="area-box-content-list"> </ul> </div> <div class="area-box-content-panel"> <ul class="area-box-content-list"> </ul> </div> <div class="area-box-content-panel"> <ul class="area-box-content-list"> </ul> </div> </div> </div> </div> </div> </body> <script type="text/javascript"> /* 添加事件监听函数 * obj 要添加监听的对象或元素 * eventName 事件名 * fun 监听函数的名称 * param 给监听函数传的参数, 这里就传了一个参数 */ function addEventHandler(obj, eventName, fun, param) { var fn = fun; if (param != undefined) { fn = function(e) { fun.call(this, param); //继承监听函数,并传入参数以初始化; } } if (obj.attachEvent) { obj.attachEvent('on' + eventName, fn); } else if (obj.addEventListener) { obj.addEventListener(eventName, fn, false); } else { obj["on" + eventName] = fn; } } /* * 采用事件监听给对象绑定方法后,可以解除相应的绑定 * oTarget:监听对象 * sEventType:监听事件类型,如click,mouseover * fnHandler:监听函数 */ function removeEventHandler(oTarget, sEventType, fnHandler) { if (oTarget.removeEventListener) { //监听IE9,谷歌和火狐 oTarget.removeEventListener(sEventType, fnHandler, false); } else if (oTarget.detachEvent) { oTarget.detachEvent("on" + sEventType, fnHandler); } else { delete oTarget["on" + sEventType]; } } /* * 停止冒泡行为 */ function stopBubble(e) { //如果提供了事件对象,则这是一个非IE浏览器 if (e && e.stopPropagation) //因此它支持W3C的stopPropagation()方法 e.stopPropagation(); else //否则,我们需要使用IE的方式来取消事件冒泡 window.event.cancelBubble = true; } var area_entrance = document.getElementById('area-entrance'); var area_header = area_entrance.getElementsByClassName('area-header')[0]; var area_header_tips = area_entrance.getElementsByClassName('area-header-tips')[0]; var area_header_click = area_entrance.getElementsByClassName('area-header-click')[0]; var area_header_click_input = area_entrance.getElementsByClassName('area-header-click-input')[0]; var area_box = area_entrance.getElementsByClassName('area-box')[0]; var area_box_title = area_entrance.getElementsByClassName('area-box-title')[0]; var area_box_content = area_entrance.getElementsByClassName('area-box-content'); var area_box_content_panel = area_entrance.getElementsByClassName('area-box-content-panel'); var area_box_content_list = area_entrance.getElementsByClassName('area-box-content-list'); //处理标题切换 function area_box_title_handle(e) { e = e || window.event; //IE window.event var t = e.target || e.srcElement; //目标对象 //标题切换 for (var i = 0; i < area_box_title.children[0].children.length; i++) { if (area_box_title.children[0].children[i] == t) { //把当前标题背景设置为白色 area_box_title.children[0].children[i].classList.add('area-box-title-current'); //显示当前列表 area_box_content_panel[i].classList.add('area-box-content-visible'); } else { //把其余标题背景设置为灰色 area_box_title.children[0].children[i].classList.remove('area-box-title-current'); //隐藏其余列表显示 area_box_content_panel[i].classList.remove('area-box-content-visible'); } } } //省级标题背景变白色 area_box_title.children[0].children[0].classList.add('area-box-title-current'); //省级标题绑定点击事件 addEventHandler(area_box_title.children[0].children[0], 'click', area_box_title_handle); //显示省级列表 area_box_content_panel[0].classList.add('area-box-content-visible'); //获取省级节点数组 var province = getSubLevel('0'); //添加节点到展示列表 for (var i = 0; i < province.length; i++) { area_box_content_list[0].innerHTML += '<li code=' + province[i].code + '>' + province[i].name + '</li>'; } //为父节点绑定省级节点点击事件,2020-01-03 addEventHandler(area_box_content_list[0], 'click', area_box_content_list_handle, 0); //切换选择列表 function area_header_click_toggle(e) { e = e || window.event; //IE window.event var t = e.target || e.srcElement; //目标对象 //切换 选择列表 if(document.defaultView.getComputedStyle(area_box).display== 'none'){ area_box.classList.add('area-box-content-visible'); }else{ area_box.classList.remove('area-box-content-visible'); } //取消冒泡 stopBubble(e); } //地址栏绑定点击事件 addEventHandler(area_header_click, 'click', area_header_click_toggle); //弹出选择列表 function area_header_click_handle(e) { e = e || window.event; //IE window.event var t = e.target || e.srcElement; //目标对象 //显示选择列表 area_box.classList.add('area-box-content-visible'); //取消冒泡 stopBubble(e); } //展示列表绑定点击事件 addEventHandler(area_box, 'click', area_header_click_handle); //关闭选择列表 function close_area_box_handle() { //隐藏选择列表 area_box.classList.remove('area-box-content-visible'); } //文档其余部分绑定点击事件 addEventHandler(document, 'click', close_area_box_handle); //本级节点绑定点击事件 function area_box_content_list_handle(index, e) { e = e || window.event; //IE window.event var t = e.target || e.srcElement; //目标对象 //点击上级节点不处理,2020-01-03 if (t.tagName != 'LI') return; //获取下级行政区划 var arrSubLevel = getSubLevel(t.getAttribute('code')); var fillContent; //当前选择节点变蓝色 for (var i = 0; i < area_box_content_list[index].children.length; i++) { if (area_box_content_list[index].children[i] == t) { t.classList.add('area-current'); } else { area_box_content_list[index].children[i].classList.remove('area-current'); } } //清空本级及后续输入地址 for (var i = area_header_click_input.children.length - 1; i >= index; i--) { area_header_click_input.children[i].outerHTML = ''; } //选中地址填充到输入框 fillContent='<span><span class="area-input-name">' + t.innerText ; //街道没有斜线 if (index == 3){ fillContent+='</span><span class="area-input-symbol"></span></span>'; }else{ fillContent+='</span><span class="area-input-symbol">/</span></span>'; } //暂不选择不进入输入框 if(t.innerText=='暂不选择'){ fillContent=''; } area_header_click_input.innerHTML += fillContent; //点击街道退出 if (index == 3){ close_area_box_handle(); //取消冒泡 stopBubble(e); return; } //次级标题绑定点击事件 if (area_box_title.children[0].children.length > index + 1) { addEventHandler(area_box_title.children[0].children[index + 1], 'click', area_box_title_handle); } //取消后续标题绑定点击事件 for (var i = area_box_title.children[0].children.length - 1; i > index + 1; i--) { removeEventHandler(area_box_title.children[0].children[i], 'click', area_box_title_handle); } //标题切换至下级 area_box_title.children[0].children[index + 1].classList.add('area-box-title-current'); area_box_content_panel[index + 1].classList.add('area-box-content-visible'); //隐藏本级标题 area_box_title.children[0].children[index].classList.remove('area-box-title-current'); area_box_content_panel[index].classList.remove('area-box-content-visible'); //填充次级可选节点,首先清空 area_box_content_panel[index + 1].children[0].innerHTML = ''; if (index == 2){ area_box_content_panel[index + 1].children[0].innerHTML += '<li code=' + '0' + '>' + '暂不选择' + '</li>'; } for (var i = 0; i < arrSubLevel.length; i++) { area_box_content_panel[index + 1].children[0].innerHTML += '<li code=' + arrSubLevel[i].code + '>' + arrSubLevel[i].name + '</li>'; } //为父节点绑定可选节点点击事件,2020-01-03 addEventHandler(area_box_content_panel[index + 1].children[0], 'click', area_box_content_list_handle, index + 1); } //根据所选地址code查找子级节点,返回数组,找不到返回undefined function getSubLevel(code) { var cities, areas, streets, rValue; if (!code) { return; } //点击地址栏,返回所有节点 if (code == '0') { rValue = pcas; return rValue; } var code2 = code.substring(0, 2); //点击省级节点,返回市级列表数组 for (var i = 0; i < pcas.length; i++) { if (pcas[i].code == code) { //刚好是省级节点 rValue = pcas[i].children; return rValue; } else if (pcas[i].code == code.substring(0, 2)) { //前两位是省级节点 cities = pcas[i].children; break; } } //点击市级节点,返回区级列表数组 if (cities) { for (var i = 0; i < cities.length; i++) { if (cities[i].code == code) { rValue = cities[i].children; return rValue; } else if (cities[i].code == code.substring(0, 4)) { areas = cities[i].children; break; } } } //点击区级节点,返回街道列表数组 if (areas) { for (var i = 0; i < areas.length; i++) { if (areas[i].code == code) { rValue = areas[i].children; return rValue; } else if (areas[i].code == code.substring(0, 6)) { streets = areas[i].children; break; } } } return rValue; } </script> </html>

浙公网安备 33010602011771号