原生JS實(shí)現(xiàn)省市區(qū)(縣)三級(jí)聯(lián)動(dòng)選擇

wo e le

原文地址→看過(guò)來(lái)

寫(xiě)在前面

前段時(shí)間寫(xiě)一個(gè)關(guān)于天氣的東西,里面的省市區(qū)(縣)城市選擇讓我很頭疼,在網(wǎng)上搜索出來(lái)大都是借助插件或者第三方庫(kù),感覺(jué)這樣做代碼會(huì)很重,所以索性就把幾種城市選擇的方式實(shí)現(xiàn)一遍,以備日后的不時(shí)之需。這三種方法都是針對(duì)pc端的,并且都是使用原生js實(shí)現(xiàn)的,連jq都沒(méi)使用,于是代碼有點(diǎn)繁瑣額(尷尬)。。。。不過(guò)還是讓我把原理講完吧。

源代碼地址→傳送門(mén)

預(yù)覽地址→傳送門(mén)

方法一:下拉選擇框?qū)崿F(xiàn)省市區(qū)(縣)三級(jí)聯(lián)動(dòng)

  1. 用下拉框?qū)崿F(xiàn)省市區(qū)三級(jí)聯(lián)動(dòng)是很常見(jiàn)的一種方式,也很方便。這里需要先了解下select的相關(guān)屬性及其對(duì)象屬性,請(qǐng)參考此文
  2. 先看下最終實(shí)現(xiàn)效果圖:


    select實(shí)現(xiàn)三級(jí)聯(lián)動(dòng)
  3. 思路介紹:
    • 頁(yè)面加載時(shí),動(dòng)態(tài)獲取省份列表并放到下拉菜單的下拉項(xiàng)中:


      select-省份顯示
    /*自動(dòng)加載省份列表*/
(function showProv() {
    btn.disabled = true;
    var len = provice.length;
    for (var i = 0; i < len; i++) {
        var provOpt = document.createElement('option');
        provOpt.innerText = provice[i]['name'];
        provOpt.value = i;
        prov.appendChild(provOpt);
    }
})();
  • 當(dāng)點(diǎn)擊省份列表中的某一項(xiàng),此時(shí)觸發(fā)省份下拉框的onchange事件,在onchange事件中根據(jù)前面所選的省份來(lái)顯示對(duì)應(yīng)城市。這里用到一個(gè)select的selectedIndex屬性,從而獲取剛剛點(diǎn)擊的是哪個(gè)省份(生成省份列表時(shí)添加了value屬性值):
    select-省份顯示
    var val = obj.options[obj.selectedIndex].value;  //這里得到的是所選擇省份在所有下拉項(xiàng)中為第幾項(xiàng)
  • 當(dāng)點(diǎn)擊城市列表中的某一項(xiàng)時(shí),原理同上(此處不贅述)


    select-省份顯示
  • 選擇城市時(shí)存在兩種情況,如何城市選項(xiàng)下不存在縣區(qū),則直接將所選省市顯示在輸入框,否則依照上訴原理顯示縣區(qū)
    <!--方法是判斷縣區(qū)的length是否為0-->
    var countryLen = provice[current.prov]["city"][val].districtAndCounty.length;
        if(countryLen == 0){
            addrShow.value = provice[current.prov].name + '-' + provice[current.prov]["city"][current.city].name;
            return;
        }
  • 最后點(diǎn)擊縣區(qū)后再按確定,則可將所選地點(diǎn)顯示在輸入框中。
  1. 注意:
    • 在未選中具體縣區(qū)時(shí),按鈕為不可點(diǎn)狀態(tài)
    • 具體的實(shí)現(xiàn)主要根據(jù)城市數(shù)據(jù)來(lái)進(jìn)行更細(xì)的處理。
  2. 說(shuō)明:
    • 這里使用的省市區(qū)數(shù)據(jù)來(lái)源于網(wǎng)絡(luò),不能保證真實(shí)性及完整性,僅供案例使用
    • 此處使用的數(shù)據(jù)類(lèi)型為js數(shù)組,格式參考如下(完整版):
var provice = [
    {
        name: "北京市",
        city: [
            {
                name: "北京市",
                districtAndCounty: ["東城區(qū)", "西城區(qū)", "崇文區(qū)", "宣武區(qū)", "朝陽(yáng)區(qū)", "豐臺(tái)區(qū)", "石景山區(qū)", "海淀區(qū)", "門(mén)頭溝區(qū)", "房山區(qū)", "通州區(qū)", "順義區(qū)", "昌平區(qū)", "大興區(qū)", "懷柔區(qū)", "平谷區(qū)", "密云縣", "延慶縣", "延慶鎮(zhèn)"]
            }
        ]
    },
    
    ......
    
    {
        name: "河北省",
        city: [
            {
                name: "石家莊市",
                districtAndCounty: ["長(zhǎng)安區(qū)", "橋東區(qū)", "橋西區(qū)", "新華區(qū)", "裕華區(qū)", "井陘礦區(qū)", "辛集市", "藁城市", "晉州市", "新樂(lè)市", "鹿泉市", "井陘縣", "微水鎮(zhèn)", "正定縣", "正定鎮(zhèn)", "欒城縣", "欒城鎮(zhèn)", "行唐縣", "龍州鎮(zhèn)", "靈壽縣", "靈壽鎮(zhèn)", "高邑縣", "高邑鎮(zhèn)", "深澤縣", "深澤鎮(zhèn)", "贊皇縣", "贊皇鎮(zhèn)", "無(wú)極縣", "無(wú)極鎮(zhèn)", "平山縣", "平山鎮(zhèn)", "元氏縣", "槐陽(yáng)鎮(zhèn)", "趙縣", "趙州鎮(zhèn)"]
            },
            
            .......
            
            {
                name: "邯鄲市",
                districtAndCounty: ["叢臺(tái)區(qū)", "邯山區(qū)", "復(fù)興區(qū)", "峰峰礦區(qū)", "武安市", "邯鄲縣", "南堡鄉(xiāng)東小屯村", "臨漳縣", "臨漳鎮(zhèn)", "成安縣", "成安鎮(zhèn)", "大名縣", "大名鎮(zhèn)", "涉縣", "涉城鎮(zhèn)", "磁縣", "磁州鎮(zhèn)", "肥鄉(xiāng)縣", "肥鄉(xiāng)鎮(zhèn)", "永年縣", "臨洺關(guān)鎮(zhèn)", "邱縣", "新馬頭鎮(zhèn)", "雞澤縣", "雞澤鎮(zhèn)", "廣平縣", "廣平鎮(zhèn)", "館陶縣", "館陶鎮(zhèn)", "魏縣", "魏城鎮(zhèn)", "曲周縣", "曲周鎮(zhèn)"]
            }
        ]
    }
]
    

方法二:按級(jí)選中省市縣/區(qū)

  1. 這種方式比上面的下拉框更好看點(diǎn),操作也更方便點(diǎn),不過(guò)大概的邏輯有點(diǎn)類(lèi)似。所用省市區(qū)數(shù)據(jù)跟上面的一致。
  2. 先看看這種方式的效果圖:


    按級(jí)選中省市縣/區(qū)
  3. 在頁(yè)面加載時(shí)同樣先顯示出所有的省份列表(方法類(lèi)似)


    按級(jí)選中省市縣/區(qū)
  4. 點(diǎn)擊具體省份時(shí),將省份列表替換成對(duì)應(yīng)的城市列表,點(diǎn)擊具體城市時(shí)顯示對(duì)應(yīng)縣區(qū),實(shí)現(xiàn)如下:
addrWrap.onclick = function (e) {     //將點(diǎn)擊事件委托給列表的父元素
    var n;
    var e = e || window.event;
    var target = e.target || e.srcElement;
    if (target && target.nodeName == 'LI') {
        /*先判斷當(dāng)前顯示區(qū)域顯示的是省市區(qū)的那部分*/
        for (var z = 0; z < 3; z++) {
            if (titleWrap[z].className == 'titleSel')
                n = z;
        }
        /*顯示的處理函數(shù)*/
        switch (n) {
            case 0:
                showCity2(target.index);   //點(diǎn)擊的是省份中列表的某一項(xiàng),接下來(lái)則顯示城市列表
                break;
            case 1:
                showCountry2(target.index);  //點(diǎn)擊的是城市列表中的某一項(xiàng),接下來(lái)則顯示縣區(qū)列表
                break;
            case 2:
                selectCountry(target.index);  //點(diǎn)擊具體的某個(gè)縣區(qū),則將該縣區(qū)選擇
                break;
            default:
                showProv2();
        }
    }
};
按級(jí)選中省市縣/區(qū)

按級(jí)選中省市縣/區(qū)
  1. 上面點(diǎn)擊的每一步中將選中項(xiàng)的索引及值保存在一個(gè)對(duì)象中,以便最后點(diǎn)擊確定按鈕將選擇的省市區(qū)顯示在輸入框中。
  2. 當(dāng)選擇的城市不存在縣區(qū)時(shí)處理跟第一種方式一致。
  3. 當(dāng)點(diǎn)擊分類(lèi)時(shí),顯示對(duì)應(yīng)的內(nèi)容,同時(shí)將保存的對(duì)象的值進(jìn)行處理:


    點(diǎn)擊不同分類(lèi)
        //將事件委托給父元素,根據(jù)點(diǎn)擊的分類(lèi)進(jìn)行處理(html的設(shè)置好li的value值)
        if (target.value == '0') {
            showProv2();  
        } else if (target.value == '1') {
            showCity2(current2.prov);
        } else {
            showCountry2(current2.city);
        }
  1. OK

方法三:按字母順序選中城市

  1. 直接按字母的順序選中城市這種方式比前兩種更簡(jiǎn)單粗暴也較為簡(jiǎn)單,代碼量也較少。
  2. 先看看這種方式的效果圖:


    按字母順序選中城市
  3. 頁(yè)面加載時(shí)先顯示熱門(mén)城市


    按字母順序選中城市
  4. 點(diǎn)擊不同字母集,顯示對(duì)應(yīng)的城市列表
switch (index) {
            case 0:    //0為熱門(mén)項(xiàng)
                showHotCity();
                break;
            case 6:    //6為最后一欄,字母集個(gè)數(shù)為2
                showCitys(index, 2);
                break;
            default:   //其余索引,字母集個(gè)數(shù)都為4
                showCitys(index, 4);
        }
function showCitys(index, m) {
    //通過(guò)傳入的參數(shù)截取城市數(shù)據(jù)的一部分為當(dāng)前要顯示的城市列表
    var currentAll = cityAll.slice(4 * index - 3, 4 * index + m - 3);  
    
    .....
    
    //將動(dòng)態(tài)生成的列表項(xiàng)放到顯示區(qū)域
}
  1. 點(diǎn)擊具體某一個(gè)城市時(shí),將其顯示在輸入框中。


    按字母順序選中城市
  2. 這種方式的城市數(shù)據(jù)跟前兩種不同,來(lái)源于網(wǎng)上,不能保證真實(shí)性及完整性,僅供案例使用,數(shù)據(jù)格式如下(完整版):
var cityAll = [
    {
        name: "hot",
        citys: ["北京", "上海", "廣州", "深圳", "杭州", "南京", "成都", "重慶", "武漢", "長(zhǎng)沙", "昆明"]
    },
    {
        name: "A",
        citys: ["阿壩", "阿拉善", "阿里", "安康", "安慶", "鞍山", "安順", "安陽(yáng)", "澳門(mén)"]
    },
    
    ......
    
    
    {
        name: "Z",
        citys: ["雜多縣", "贊皇縣", "棗強(qiáng)縣", "棗陽(yáng)市", "棗莊",.......,資陽(yáng)"]
}

7.完美~

小結(jié)

  1. 詳細(xì)代碼看上面給出了鏈接,有注釋的額(firefox和chrome可正常顯示)~
  2. 這幾種實(shí)現(xiàn)方式為一己之見(jiàn),歡迎大佬們指點(diǎn),如有更好的可以告訴我,我來(lái)完善完善~
  3. 有人能告訴我怎么做gif圖么?
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀(guān)點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容