# Lesson-10
---
實現on,off的事件委托!
我們能根據之前的思路,利用同樣的方法實現一個事件委托.
先來看看流程圖

然后先看看結果是如何,畢竟流程圖看的也不一定能懂。

最后我們再來看看代碼
```javascript
Kodo.deleEvents = []; //事件委托存放的事件
Kodo.deleId = 0; //事件委托的唯一標識
on: function(type, selector, fn) {
if (typeof selector == 'function') {
fn = selector; //兩個參數的情況
//事件綁定過程
} else {
//事件委托過程
for (var i = 0; i < this.length; i++) {
if ( !this[i].deleId ) {
this[i].deleId = ++Kodo.deleId;
//同樣是判斷是否有唯一id
Kodo.deleEvents[Kodo.deleId] = {};
//沒有則創建id對象 也就是f.deleEvents[]新開辟一個新對象
Kodo.deleEvents[Kodo.deleId][selector] = {};
//構造 selector對象
/*
* 如 Kodo.deleEvents[1] =
* {
* "#box li" : {},
* "#pox" : {}
* }
*/
Kodo.deleEvents[Kodo.deleId][selector][type] = [fn];
//構造我們的事件數組
/*
* 如 Kodo.deleEvents["#box li"] =
* {
* "click" : [fn1,fn2...],
* "touchstart" : [fn1,fn2....]
* }
*/
delegate(this[i],type,selector);
//用委托的方式進行綁定
} else {
//如果id存在的情況
var id = this[i].deleId,
position = Kodo.deleEvents[id];//委托元素的事件存儲位置
if(!position[selector]) {
//先判斷如果selector存儲的對象不存在
position[selector] = {};
//新建selector對象 (與上面的selector構造相同)
position[selector][type] = [fn];
//構造事件數組對象 (與上面的type構造相同)
delegate(this[i],type,selector);
//因為是新的selector 所以要再綁定
} else {
//selector 存儲對象存在的情況
if ( position[selector][type] ) {
//如果事件數組已經有了,則直接push進來
position[selector][type].push(fn);
} else {
//如果事件數組沒有,那就構造事件數組
position[selector][type] = [fn];
//因為是新的綁定的事件,所以要重新綁定
delegate(this[i],type,selector);
}
}
}
}
}
},
```
繼續再看一遍log的結果,對比剛剛的代碼

連同代碼,我在注釋里已經非常的詳細解釋了整個過程,大家結合控制臺log的結果,在看看最初的流程圖結合的看,我相信有點點耐心就能馬上理解了。
綁定過程都會比較復雜,理解了綁定過程后,下面off的實現就很容易了。
off本身是可以傳2個參數的,第一個參數為事件type,第二個參數是委托元素selector
```javascript
off: function(type, selector) {
if (arguments.length == 0) {
//如果沒傳參數,清空所有事件
} else if (arguments.length == 1) {
//指定一個參數,則清空對應的事件
} else {
//直接根據dom上存有的deleId,找到對應的deleEvents里的位置
//刪除委托元素上的type事件數組即可
for (var i = 0; i < this.length; i++) {
var id = this[i].deleId;
delete Kodo.deleEvents[id][selector][type];
}
}
}
```
最后看看我們修改過后的 delegate方法
```javascript
function delegate(agent, type, selector) {
var id = agent.deleId; //先獲取被委托元素的deleId
agent.addEventListener(type, function(e) {
var target = e.target;
var ctarget = e.currentTarget;
var bubble = true;
while (bubble && target != ctarget) {
if (filiter(agent, selector, target)) {
for (var i = 0; i < Kodo.deleEvents[id][selector][type].length; i++) {
bubble = Kodo.deleEvents[id][selector][type][i].call(target, e);
//循環事件數組 直接call
}
}
target = target.parentNode;
return bubble;
}
}, false);
function filiter(agent, selector, target) {
//過濾函數
}
}
```
這里修改的就只有二個地方
1.獲取被委托元素的deleId,因為我們整個委托機制都與他有關。
2.通過id在deleEvents里查找對應的事件數組,循環執行即可
以上就是整個委托的過程!
```javascript
f("you").on('star','me',function(){
console.log('success!');
});
```