原生JS實現省市區(縣)三級聯動選擇

wo e le

原文地址→看過來

寫在前面

前段時間寫一個關于天氣的東西,里面的省市區(縣)城市選擇讓我很頭疼,在網上搜索出來大都是借助插件或者第三方庫,感覺這樣做代碼會很重,所以索性就把幾種城市選擇的方式實現一遍,以備日后的不時之需。這三種方法都是針對pc端的,并且都是使用原生js實現的,連jq都沒使用,于是代碼有點繁瑣額(尷尬)。。。。不過還是讓我把原理講完吧。

源代碼地址→傳送門

預覽地址→傳送門

方法一:下拉選擇框實現省市區(縣)三級聯動

  1. 用下拉框實現省市區三級聯動是很常見的一種方式,也很方便。這里需要先了解下select的相關屬性及其對象屬性,請參考此文
  2. 先看下最終實現效果圖:


    select實現三級聯動
  3. 思路介紹:
    • 頁面加載時,動態獲取省份列表并放到下拉菜單的下拉項中:


      select-省份顯示
    /*自動加載省份列表*/
(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);
    }
})();
  • 當點擊省份列表中的某一項,此時觸發省份下拉框的onchange事件,在onchange事件中根據前面所選的省份來顯示對應城市。這里用到一個select的selectedIndex屬性,從而獲取剛剛點擊的是哪個省份(生成省份列表時添加了value屬性值):
    select-省份顯示
    var val = obj.options[obj.selectedIndex].value;  //這里得到的是所選擇省份在所有下拉項中為第幾項
  • 當點擊城市列表中的某一項時,原理同上(此處不贅述)


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

方法二:按級選中省市縣/區

  1. 這種方式比上面的下拉框更好看點,操作也更方便點,不過大概的邏輯有點類似。所用省市區數據跟上面的一致。
  2. 先看看這種方式的效果圖:


    按級選中省市縣/區
  3. 在頁面加載時同樣先顯示出所有的省份列表(方法類似)


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

按級選中省市縣/區
  1. 上面點擊的每一步中將選中項的索引及值保存在一個對象中,以便最后點擊確定按鈕將選擇的省市區顯示在輸入框中。
  2. 當選擇的城市不存在縣區時處理跟第一種方式一致。
  3. 當點擊分類時,顯示對應的內容,同時將保存的對象的值進行處理:


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

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

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


    按字母順序選中城市
  3. 頁面加載時先顯示熱門城市


    按字母順序選中城市
  4. 點擊不同字母集,顯示對應的城市列表
switch (index) {
            case 0:    //0為熱門項
                showHotCity();
                break;
            case 6:    //6為最后一欄,字母集個數為2
                showCitys(index, 2);
                break;
            default:   //其余索引,字母集個數都為4
                showCitys(index, 4);
        }
function showCitys(index, m) {
    //通過傳入的參數截取城市數據的一部分為當前要顯示的城市列表
    var currentAll = cityAll.slice(4 * index - 3, 4 * index + m - 3);  
    
    .....
    
    //將動態生成的列表項放到顯示區域
}
  1. 點擊具體某一個城市時,將其顯示在輸入框中。


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

7.完美~

小結

  1. 詳細代碼看上面給出了鏈接,有注釋的額(firefox和chrome可正常顯示)~
  2. 這幾種實現方式為一己之見,歡迎大佬們指點,如有更好的可以告訴我,我來完善完善~
  3. 有人能告訴我怎么做gif圖么?
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,825評論 6 546
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,814評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 178,980評論 0 384
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 64,064評論 1 319
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,779評論 6 414
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 56,109評論 1 330
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,099評論 3 450
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,287評論 0 291
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,799評論 1 338
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,515評論 3 361
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,750評論 1 375
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,221評論 5 365
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,933評論 3 351
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,327評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,667評論 1 296
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,492評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,703評論 2 380

推薦閱讀更多精彩內容