制作時間:13:30 - 15:30
之前做網(wǎng)站接觸過城市二級聯(lián)動,但也只是從網(wǎng)上copy的一段代碼修修剪剪就用了。今天跟著視頻自己動手實現(xiàn)了這個迷你效果。不過數(shù)據(jù)比較不正規(guī),全是數(shù)字。

1. 首先建立一個容器:
<div id="box"></div>
2. 因為這種效果比價常用,所以用面向?qū)ο蟮乃枷刖帉懘a。
創(chuàng)建一個構(gòu)造函數(shù),并編寫原型中的方法。
var s1 = new Sel('box');
function Sel(id){
.........
}
Sel.prototype = {
.........
}
3. 添加數(shù)據(jù),所以創(chuàng)建一個add方法:
首先在構(gòu)造函數(shù)中添加語句,創(chuàng)建一個大的json數(shù)據(jù):
this.data = {};
然后添加add方法:
Sel.prototype = {
add: function(key,value){
this.data[key] = value;
}
}
調(diào)用方法,設置數(shù)據(jù)格式為json格式:
s1.add('0',['1','2','3']);
s1.add('0_0',['1.1','1.2','1.3']);
s1.add('0_0_0',['1.1.1','1.1.2','1.1.3']);
s1.add('0_0_1',['1.2.1','1.2.2','1.2.3']);
s1.add('0_0_2',['1.3.1','1.3.2','1.3.3']);
s1.add('0_1',['2.1','2.2','2.3']);
s1.add('0_1_0',['2.1.1','2.1.2','2.1.3']);
s1.add('0_1_1',['2.2.1','2.2.2','2.2.3']);
s1.add('0_1_2',['2.3.1','2.3.2','2.3.3']);
s1.add('0_2',['3.1','3.2','3.3']);
s1.add('0_2_0',['3.1.1','3.1.2','3.1.3']);
s1.add('0_2_1',['3.2.1','3.2.2','3.2.3']);
s1.add('0_2_2',['3.3.1','3.3.2','3.3.3']);
4. 創(chuàng)建一個 init 方法
可以設置多選框的個數(shù)。這個例子是三級聯(lián)動,所以設置3個多選框。
init: function(num){
for(var i=1;i<=num;i++){
var oSel = document.createElement("select");
var oPt = document.createElement("option");
oPt.innerHTML = "默認";
oSel.appendChild(oPt);
this.oParent.appendChild(oSel);
}
}
然后在之前調(diào)用一下 init 方法。
s1.init(3);
此時的效果圖是這樣的,還沒有數(shù)據(jù):

5. 初始化時使第一級菜單的內(nèi)容顯示出來,創(chuàng)建一個 first 方法:

橫線1 :
this.data['0']的數(shù)據(jù)就是“默認”, “1”,“2”,“3”
橫線2 : 需要將opt元素添加到第一個select上。那么需要先獲取到第一個select元素。所以要在構(gòu)造函數(shù)中添加這條語句:
this.aSel = this.oParent.getElementsByTagName("select");
自然而然了, this.aSel[0] 就是第一個select.
最后在 init 初始化方法中調(diào)用一下 first 方法:
this.first();
6. 接下去就是將第二個,第三個select與第一個聯(lián)動起來。
我們在任何一個select中選擇時,都會觸發(fā)onchange事件,所以在剛開始創(chuàng)建3個select的代碼時,添加onchange事件。
在這個事件中調(diào)用change方法,把select的索引值約當中參數(shù)傳遞過去。
所以 init 方法改進成:

- 將this保存起來,因為在onchange事件中,this改變了,變成了oSel對象。
- 把 i 賦給 oSel.index ,可以方便控制change函數(shù)中的代碼。
比如第一個select觸發(fā)onchange,那么通過change(1),可以改變索引值為1 , 即第二個select的內(nèi)容。
7. 具體的change方法代碼:

分析一下:
假如選擇第一個select中的第一個選項“1”,那么就會執(zhí)行change(1)。
inow = 1
this.aSel[i].selectedIndex -1 = 0
所以 str 就變成 "0_0"
查看之前創(chuàng)建的json數(shù)據(jù): s1.add('0_0',['1.1','1.2','1.3'])
通過 var arr = this.data[str]; 獲取一下數(shù)據(jù)“1.1”,“1.2”,“1.3”
通過 for 循環(huán)把數(shù)據(jù)添加到元素中顯示。
那為什么要判斷 this.data[str] 呢?
因為我們通過 this.aSel[i].selectedIndex -1 獲取選中元素的索引值減 1 。如果選中 “默認” ,那么這個值會變?yōu)?-1 ,當然也就沒有this.data["0_-1"] 的數(shù)據(jù)了。
所以在這個 else 中,通過 this.aSel[inow].options.length = 1; 將該select的值改為 “ 默認” 。
8. 問題: 先選中第一個select中的1,再選中2.查看第二個select,是如下的結(jié)果:

原因: 在選中 1 后,把 "0_0" 對應的數(shù)據(jù) append 上去了。再選中 2 ,又把 "0_1" 的數(shù)據(jù)也 append 上去了。
解決:在 if(this.data[str]) 中添加 this.aSel[inow].options.length = 1; ,使得每次 append 之前把先前的數(shù)據(jù)刪掉。
9. 問題: 選中第一個select中的 1,第二個select和第三個都顯示 “默認”,而不會自動顯示第一個元素。如圖:

添加:
this.aSel[inow].options[1].selected = true;如圖:

再添加:
inow++;
if(inow < this.aSel.length){
this.change(inow);
}
如圖:

聯(lián)動下拉菜單效果結(jié)束
不積跬步無以至千里