最近邊上班邊做畢設(感覺自己馬上要接到離職通知書了),好久沒寫原生js,遇到一個問題,前端請求返回了一個部門Json數組,大概長這樣:
var json = [{
dId: 1,
level: 0,
dName: '研發中心',
pid: ''
}, {
dId: 101,
level: 1,
dName: '部門1',
pid: 1
}, {
dId: 102,
level: 1,
dName: '部門2',
pid: 1
}, {
dId: 103,
level: 1,
dName: '部門3',
pid: 1
}, {
dId: 10101,
level: 2,
dName: '小組1',
pid: 101
},{
dId: 10102,
level: 2,
dName: '小組2',
pid: 101
},{
dId: 10201,
level: 2,
dName: '小組1',
pid: 102
},{
dId: 10202,
level: 2,
dName: '小組2',
pid: 102
},{
dId: 10203,
level: 2,
dName: '小組3',
pid: 102
}];
我需要把它渲染成樹結構,這他么居然困擾了我一早上(一邊做項目組任務,一遍切換做畢設,強行解釋成精力沒辦法集中),晚上回來,認真寫寫就出來了;
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<script type="text/javascript" src="js/jquery-2.1.4.min.js" ></script>
<title>department</title>
</head>
<body>
<div id="Department"></div>
<script type="text/javascript">
$(function() {
$("#Department").on('click','span',function(){
alert($(this).siblings("input").val())
})
//模擬了后臺返回的部門json數組
var json = [{
dId: 1,
level: 0,
dName: '中心',
pid: ''
}, {
dId: 101,
level: 1,
dName: '部門1',
pid: 1
}, {
dId: 102,
level: 1,
dName: '部門2',
pid: 1
}, {
dId: 103,
level: 1,
dName: '部門3',
pid: 1
}, {
dId: 10101,
level: 2,
dName: '小組1',
pid: 101
},{
dId: 10102,
level: 2,
dName: '小組2',
pid: 101
},{
dId: 10201,
level: 2,
dName: '小組1',
pid: 102
},{
dId: 10202,
level: 2,
dName: '小組2',
pid: 102
},{
dId: 10203,
level: 2,
dName: '小組3',
pid: 102
}];
// 注意我放了事先把 department-div 給加上了,后面寫好了它的內容,直接 append 進來就好,當然也可以直接寫在后面;
var html = '<div>'
+'<div class="center-part">'+json[0].dName+'</div>'
+'<input value="'+json[0].dId+'" type="hidden"/>'
+'</div>'
+'<div class="department-part">'
+'</div>';
// 先把最高權級的中心給渲染了(這里我在設計表結構的時候偷懶了,直接默認第一個為最高級了,所以這里就直接取了,注意:一個好的習慣就是先清空內容 empty() 再 append);
$("#Department").empty().append(html);
// 早上問題就出在這了,這個department是要一直循環添加的,所以得寫在第一層 for 循環的外面;
var departmentHtml = '';
for(var i=1;i<json.length;i++){
// 偷懶again,直接在表結構中說明了它的級別,而且更偷懶的是,我指定了一共就三級,hahahahhahahaha
if (json[i].level ===1) {
// 這里少了div的結尾,因為還要判斷是否存在子級的組,所以封尾放在后面了;
departmentHtml +='<div class="department">'
+'<span>'+json[i].dName+'</span>'
+'<input value="'+json[i].dId+'" type="hidden"/>';
// 因為可能要添加多個組,所以頭尾拆開;
var groupHead = ''
+'<div class="group-part">';
// groupHtml 放在for循環的外面,可以保證每次執行完內層循環后其內容被清空,這樣就可以做下一個部門內小組的添加了;
var groupHtml = '';
for (var j= 1 ; j<json.length ; j++) {
// 判斷父級(這是表機構設計,返回的json數組格式的局限,只能這么判斷了)
if(json[j].pid === json[i].dId) {
groupHtml += '<div class="group">'
+'<span>'+json[j].dName+'</span>'
+'<input value="'+json[j].dId+'" type="hidden"/>'
+'</div>';
}
}
// groupHtml 不為空表示有子節點組級的存在,加上頭尾,否則直接給department封尾
if (groupHtml !== '') {
groupHtml = groupHead + groupHtml + '</div>';
departmentHtml = departmentHtml + groupHtml + "</div>";
} else {
departmentHtml = departmentHtml + groupHtml + "</div>";
}
}
}
// 結束最外層的for循環,直接append到部門div中;
$(".department-part").empty().append(departmentHtml);
})
</script>
</body>
</html>
結果如下(旁邊的圖標是用來點擊顯隱組級部門用的,測試而已,沒寫樣式,不要太在意):
你可能已經發現了,上面還有一個代碼沒寫注釋,我把它拎出來:
$("#Department").on('click','span',function(){
alert($(this).siblings("input").val())
})
這就是jquery的比較常用的事件綁定,用關鍵字 on(當然以前也有 bind、live、delelgate 之類的),
$(selector).on(event,childselector,data,function)
參照我的寫法,可以比較清楚的理解各個參數的意思,
- event:必需項,這可以指定一個事件:‘click’,也可以指定一組事件:‘click dbclick mouseout’;
- childselector:可選;表示需要添加事件處理程序的元素,一般為selector的子元素,沒填則表示事件綁定在 $(selector) 上;
- data:可選;需要傳遞的參數;
- function:必需項;當綁定事件發生時,需要執行的函數;
既然已經知道了這個事件綁定了,那么什么時候用它呢?個人覺得平時給dom寫事件,最好都采用綁定這樣比較穩妥,因為我們知道,事件綁定的好處就是像無賴般一旦定義了,就是死死地綁在指定選擇器對應的dom上了,不關你是原本就存在于document中的 還是后面 append進去的,只要你滿足綁定條件,事件一定會觸發。
回到之前的代碼,我的寫法是獲取我點擊的部門所對應的dId(因為我后面要根據這個id發請求去獲取用戶列表),那么當我把這段代碼寫在 script 的最前面的時候,我就得采用如上寫法,用事件綁定到 #Department 下的 span節點上(因為頁面渲染是按照文檔順序的,這時候下面進行的 append 等操作還沒被渲染,所以頁面文檔樹中還沒有這些dom,如果沒采用事件綁定 事件是肯定不會生效的)。
但如果我們把這段代碼寫在 append的后面,也就是在確保你要綁定事件的 append 已經都結束了,頁面文檔樹長已經渲染了這些 dom 了,那么你就可以不用采用事件綁定了 :
$("#Department").find("span").on('click',function(){
alert($(this).siblings("input").val())
})
這樣也可以實現同樣的功能的。
當然,個人建議是,在確認綁定事件不會影響后續操作時,能綁定的盡量去綁定吧。