很久都沒有寫東西了,如今乾的活都是重複和簡單的活,能總結出來的東西仍是不太多。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,因此現有的控件老是出問題,等這兩天優化完進行測試下,到時候在寫一篇簡單點的文章發佈出來。
能看到這裏的,你們要是有什麼問題的能夠留言跟我討論討論,有啥好的想法也能夠跟我溝通,你們一塊兒學習。
以上