很久都没有写东西了,如今干的活都是重复和简单的活,能总结出来的东西仍是不太多。css
目前作电商平台,其中用到选择地址的控件,不过不是本身写的,最近花时间从新本身作一个,目前就先吧功能样式,功能完成初版,以后再进行优化和升级,最终作成组件或者是插件形式,调用只须要几行代码去完成,不过这些都是后话了,目前显示完成基本的样子和功能。这一篇文章就当作写东西的一个笔记,记录一个过程。html
先放上出来的效果vue
看效果图挺简单的,由于懒。就用了jquery加js,方法什么的也没考虑性能啥的,就初步先作一个出来。后面再慢慢一步步优化。jquery
不肯意往下看的有兴趣的能够直接看这里 githubd selectAddress-v1.0地址git
接下来咱们进入正题!有什么问题能够留言跟我讨论,这个功能不是很复杂,只是做为粗糙版就没有考虑不少。github
接下来咱们进入正题!有什么问题能够留言跟我讨论,这个功能不是很复杂,只是做为粗糙版就没有考虑不少。web
首先至少得有想法,作成什么样子,这个很重要,要是会点设计,能够本身先作个大概的图或者原型,既然以后要作成组件,首先页面上就得有个按钮,而后弹出选择地址的弹框,页面上得有一个显示选择完地址的标签。ajax
弹框出来以后,得有几个部分,一个是顶部标题,叉叉按钮用来隐藏,接下来是每级选择完的地址显示在中间,而后就是下面的每级地址列表,而且列表中如有选中的地址则标红,这些都是最基本的。json
我这边作的地址目前只有四级地址,不会有更深层次的地址,因此只有四列。构思好了,大概样子就是下图。数组
构造页面算是最简单的部分了,就是写html,css了。写成上图的样子。
由于四级地址列表考虑到屡次切换留有缓存的问题,没有作成每切换一次就请求一次,而是作成四个列表,经过隐藏显示的方式来更方便的操做。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <meta name="viewport" content="width=device-width,initial-scale=1,user-scalable=0,minimum-scale=1, maximum-scale=1"/> <link rel="stylesheet" href="address.css"> <script src="jquery-3.2.1.min.js"></script> </head> <body> <div class="btn" onclick="show()">点击选择地址</div> <div class="show_address" id="product_address_show" onclick="show()">北京市,北京市,朝阳区,朝外街道</div> <div id="yls_address_choose" style="display: none"> <div class="yls_address_bg" onclick="hide()"></div> <div class="yls_address_main"> <div class="yls_address_pop_top"> <div class="yls_address_pop_title">请选择地址</div> <div class="yls_address_pop_cancel" onclick="hide()"></div> </div> <div class="yls_address_pop_main"> <div class="yls_address_product"> <div class="yls_address_select" id="yls_address_select"> <div class="yls_address_top_address jdshop_alignment_middle"> <div id="yls_top_address_1">请选择</div> <div id="yls_top_address_2"></div> <div id="yls_top_address_3"></div> <div id="yls_top_address_4"></div> </div> <div class="yls_address" id="yls_address_1"></div> <div class="yls_address" id="yls_address_2"></div> <div class="yls_address" id="yls_address_3"></div> <div class="yls_address" id="yls_address_4"></div> </div> </div> </div> </div> </div> </body> </html>
这个html仍是一目了然的,很简单,下面是css样式。
body, html { -webkit-user-select: none; user-select: none } html { -webkit-text-size-adjust: 100% } body { line-height: 1.6; background-color: #f5f5f9; color: #4a4a4a; font-size: 14px; font-family: Arial, '微软雅黑', Helvetica Neue, Helvetica, sans-serif; -webkit-overflow-scrolling: touch; overflow-scrolling: touch } * { margin: 0; padding: 0 } a img { border: 0 } a { text-decoration: none; -webkit-tap-highlight-color: transparent; -webkit-appearance: none } @font-face { font-weight: 400; font-style: normal; font-size: 14px; font-family: Arial, '微软雅黑', Helvetica Neue, Helvetica, sans-serif } input, textarea { border: 0; outline: 0; -webkit-appearance: none; -webkit-tap-highlight-color: transparent; font-size: inherit; color: inherit } /*点击选择按钮*/ .btn{ margin: 0 auto; width: calc(50%); height: 30px; margin-top: 100px; background-color: lightcyan; line-height: 30px; text-align: center; font-size: 14px; } .alignment_middle{ -webkit-box-align: center; -webkit-align-items: center; align-items: center; -webkit-box-pack: start; -webkit-justify-content: flex-start; justify-content: flex-start; display: -webkit-box; display: -webkit-flex; display: flex; } /*显示文字*/ .show_address{ margin: 0 auto; margin-top: 10px; width: 80%; height: 30px; background-color: #fff; text-align: center; line-height: 30px; font-size: 14px; } /*背景*/ .yls_address_bg { position: fixed; top: 0; left: 0; height: 100%; width: 100%; background: #000; z-index: 500; opacity: .3; -webkit-transition: opacity .3s; transition: opacity .3s; touch-action: none } /*主弹框*/ .yls_address_main { position: fixed; left: 0; width: 100%; bottom: 0; background: #fff; border-radius: 10px 10px 0 0; box-shadow: 0 0 3px #e9e9e9; -webkit-transform: translate3d(0, 120%, 0); transform: translate3d(0, 120%, 0); -webkit-transition: -webkit-transform .3s; transition: -webkit-transform .3s; transition: transform .3s; transition: transform .3s, -webkit-transform .3s; z-index: 1001; transform: translate3d(0, 0, 0); } .yls_address_pop_top { text-align: center; height: 50px; margin-bottom: 5px; } .yls_address_pop_title { height: 100%; line-height: 50px; } .yls_address_pop_cancel { position: absolute; right: 0; top: 0; width: 50px; height: 50px; } .yls_address_pop_cancel::before, .yls_address_pop_cancel::after { content: ''; width: 16px; height: 1px; background: #000; display: block; position: absolute; right: 10px; top: 25px; } .yls_address_pop_cancel::before { transform: rotate(45deg); /*进行旋转*/ } .yls_address_pop_cancel::after { transform: rotate(-45deg); } .yls_address_pop_main { } .yls_address_product{ } .yls_address_select{ height: calc(60vh); width: 100%; position: relative; overflow: hidden; } .yls_address_top_address{ font-size: 12px; height: 35px; overflow: hidden; border-bottom: 1px solid #ddd; } .yls_address_top_address>div{ padding: 5px 5px; margin: 0 5px; white-space: nowrap; } .yls_address_top_address>div.show{ color: #c91623; border-bottom: #c91623 1px solid; } .yls_address{ position: absolute; left: 0; top: 45px; overflow: auto; width: 100%; height: calc(60vh - 35px); -webkit-transform: translate3d(-100%,0,0); transform: translate3d(-100%,0,0); -webkit-transition: -webkit-transform .3s .2s; transition: -webkit-transform .3s .2s; transition: transform .3s .2s; transition: transform .3s .2s,-webkit-transform .3s .2s; } .yls_address p{ padding: 8px 10px; font-size: 14px; } .yls_address p.p_show { position: relative; color: #c91623; } .yls_address.show { -webkit-transform: translate3d(0,0,0); transform: translate3d(0,0,0); }
css上半部分是一些基本的初始化浏览器样式,下面部分就是地址选择的样式,目前还没加入动态效果,以后优化部分考虑作进去。不过这部分的样式彻底能够本身按照本身的喜爱作,想作成什么样子就作成什么样子的。
这个部分算是最重要的,不过在此重申一遍,我作的只是粗糙的版本,逻辑部分是没有通过任何优化的,这个你们能够按照本身优化的方式进行优化,后期我会作成插件形式再写一篇。😂但愿看到这篇文章的你们不要嘲笑我写的粗糙,毕竟我写这个也只是给新手看看,不要嫌弃。
1.作基本的变量声明工做
/*赋初始值*/ var startId = [1804,1805,1829,1831]; var startName = ['北京市','北京市','朝阳区','朝外街道']; //最终获取到的值 var returnStartId = []; var returnStartName = [];
2.作弹出弹框的弹出隐藏方法
/*显示地址选择,隐藏地址选择*/ function show() { document.getElementById("yls_address_choose").style.display="";//显示 var url = 'http://*********/address/areas?areaId=';//这边写你请求接口的url initAddress(url,startId,startName);//初始化工做的方法 } /*隐藏地址选择*/ function hide() { //点击隐藏的时候循环将列表全部的show样式去除,从新添加到最后一列上 for(var i = 1;i < 5;i++){ var ad = 'yls_top_address_' + i; var adid = 'yls_address_' + i; $("#"+ad).removeClass('show'); $("#"+adid).removeClass('show'); $("#"+ad).show(); $("#"+adid).show(); } document.getElementById("yls_address_choose").style.display="none";//显示 //点击隐藏了,就把最终值还原成初始值 returnStartId = startId; returnStartName = startName; }
3.作弹出弹框的初始化工做
//初始化方法 function initAddress(url,startId,startName) { //将咱们最后须要获取的值初始化成初始值 returnStartId = startId; returnStartName = startName; //初始化请求areaid=0的数据,我用的接口areaid=0的时候是请求省级地址 request(url,0,1); } //初始化请求数据部分, //thisNum 为areaid变化数值 url是请求url, addressNum是每一个address是第几个 function request(url,thisNum,addressNum){ var addressUrl = url+ thisNum; $.ajax({ type: 'get', url: addressUrl, dataType: "json", success: function (res) { //无常规错误,根绝data数据作具体的业务判断显示 console.log(res.result); //初始化的渲染html setHtml(res.result,thisNum,addressNum); //循环请求下级地址 if(addressNum < startId.length){ request(url,startId[addressNum-1],addressNum+1); addressNum += 1; } }, error: function erryFunction(err) { //网络请求错误 console.log(err); console.log('读取失败') } }); } //初始化渲染页面 function setHtml(data,thisNum,addressNum) { var addressId = 'yls_address_' + addressNum; var topAddress = 'yls_top_address_' + addressNum; if(addressNum == startId.length){ $("#"+addressId).addClass('show'); $("#"+topAddress).addClass('show'); } $("#"+topAddress).text(startName[addressNum-1]); //初始化以后选中的地址顶部tab进行添加点击方法,每次点击会作什么事情 document.getElementById(topAddress).addEventListener("click",function () { var a = parseInt(topAddress.substr(topAddress.length-1,1)); console.log(a); for(var i = 1;i < 5;i++){ var ad = 'yls_top_address_' + i; var adid = 'yls_address_' + i; if(i != a){ $("#"+ad).removeClass('show'); $("#"+adid).removeClass('show'); if(i > a){ $("#"+ad).hide(); } }else{ $("#"+ad).addClass('show'); $("#"+adid).addClass('show'); } } //tab上选中地址点击的时候,最终选择地址数组数据也要相应的变化 returnStartId = returnStartId.slice(0,addressNum); returnStartName = returnStartName.slice(0,addressNum); },false); $("#"+addressId).empty();//清空当前列表的html var html = ''; //拼接html,为地址列表中每个地址添加点击方法 if(data){ for(var i = 0;i < data.length;i++){ if(startName[addressNum-1] == data[i].name){ html += '<p class="p_show" id="add_'+data[i].areaId+'" onclick="chooseDetail('+data[i].areaId+','+addressNum+',"'+data[i].name+'")">'+data[i].name+'</p>'; }else{ html += '<p id="add_'+data[i].areaId+'" onclick="chooseDetail('+data[i].areaId+','+addressNum+',"'+data[i].name+'")">'+data[i].name+'</p>'; } } } //添加html到列表上渲染页面 $("#"+addressId).append(html); }
4.每次点选地址以后的具体逻辑
//点击列表中详细地址的方法 function chooseDetail(areaId,addressNum,name) { var url = 'http://******/address/areas?areaId='; var adid = 'add_'+areaId; var adid1 = 'yls_address_' + addressNum; //选中的数据加上标红显示 $("#"+adid1+'>p').removeClass('p_show'); $("#"+adid).addClass('p_show'); //点击具体地址以后,将最终选择地址数组中相应位置的数据替换掉 returnStartId[addressNum-1] = areaId; returnStartName[addressNum-1] = name; //判断是不是第四级地址,若是是第四级地址,把获取到的数据渲染到页面上,而且隐藏弹框 //若是是第四级地址,发送请求获取下一级的数据进行渲染页面 if(addressNum == 4){ var topAddress1 = 'yls_top_address_' + addressNum; $("#"+topAddress1).text(name); $("#product_address_show").text(returnStartName); hide(); }else{ newrequest(url,areaId,addressNum,name); } } //点击列表里具体地址,发送新的请求获取下一级数据 //thisNum 为areaid变化数值 url是请求url, addressNum是每一个address是第几个,name是你选择的地址具体名称 function newrequest(url,thisNum,addressNum,name){ var addressUrl = url+ thisNum; $.ajax({ type: 'get', url: addressUrl, dataType: "json", success: function (res) { //无常规错误,根绝data数据作具体的业务判断显示 console.log(res.result); //获取到数据以后渲染下一级列表 setHtml2(res.result,thisNum,addressNum,name); }, error: function erryFunction(err) { //网络请求错误 console.log(err); console.log('读取失败') } }); } //选择详细地址请求获取数据以后渲染方法 function setHtml2(data,thisNum,addressNum,name) { //获取到相应的div var adid1 = 'yls_address_' + addressNum; var adid2 = 'yls_address_' + (addressNum+1); var topAddress1 = 'yls_top_address_' + addressNum; var topAddress2 = 'yls_top_address_' + (addressNum+1); //清空相应的下一级div和下一级tab上选中的地址,填入新的数据 $("#"+topAddress2).empty(); $("#"+adid2).empty(); $("#"+topAddress2).addClass('show'); $("#"+topAddress2).show(); $("#"+topAddress1).removeClass('show'); $("#"+adid2).addClass('show'); $("#"+adid1).removeClass('show'); $("#"+topAddress2).text('请选择'); $("#"+topAddress1).text(name); var html = ''; if(data){ //拼接html,而且添加上新的详细地址选择方法 for(var i = 0;i < data.length;i++){ html += '<p id="add_'+data[i].areaId+'" onclick="chooseDetail('+data[i].areaId+','+(addressNum+1)+',"'+data[i].name+'")">'+data[i].name+'</p>'; } } $("#"+adid2).append(html); }
以上三步就完成了地址选择粗糙版的构造,其中用来请求数据的方法写了两个,拼接html渲染页面的方法也写了两个,这些是有点冗余的,这个部分以后能够合成一个。
目前优化的构思是有,不过还没来得及实施,得找时间作一下,优化的思路是其中的方法先进行相应的优化,最后集成成一个对象,在页面调用的时候只要把初始化数据传入,最后加上一个回调方法,将选择完成的地址返回回来,这样整个页面也呢个简洁不少,调用方法也简单了,使用起来的话会方便不少。
由于目前我写的vue的单页面应用,用到keepAlive,因此现有的控件老是出问题,等这两天优化完进行测试下,到时候在写一篇简单点的文章发布出来。
能看到这里的,你们要是有什么问题的能够留言跟我讨论讨论,有啥好的想法也能够跟我沟通,你们一块儿学习。
以上