1. 程式人生 > >javascript-委託事件(事件代理)

javascript-委託事件(事件代理)

1.什麼是委託事件?

委託事件也叫做事件代理意思是一樣的,就好像精靈圖也叫 雪碧圖!!!只是不同叫法.
試想一下:假設公司裡每次收快遞的時候員工都跑到公司門口去收自己的快遞,如果同時多個人也同樣去收自己快遞這樣公司就秩序混輪了!如果委託給前臺妹子去收快遞然後由妹子去派發快遞這個過程就叫委託事件!(備註:冒泡思想也有點相仿只不過是由父節點往子節點傳遞資訊)

2.javascript委託事件的例子

1.通過冒泡事件來形象理解委託思想

<!DOCTYPE html>
<html>
    <head>
        <meta charset
='UTF-8'>
<title>原生委託事件</title> <style type='text/css'> ul{background:#f40} ul li {background: #ccc;} </style> </head> <body> <ul id='ul'> <li>11312</li> <li>
23213</li> <li>33123</li> </ul> <button id='oBtn'>新增節點</button> </body> <script type='text/javascript'> var elm=document.getElementById('ul'); //引發冒泡事件 elm.onclick=function(eve){ let evevts=eve||window.event; let
ev=events.target||events.srcElements; alert(ev.nodeName.toLowerCase()) }
</script> </html>

2.IE相容:window.event.srcElement而其他瀏覽器使用window.event.target

<!DOCTYPE html>
<html>
    <head>
        <meta charset='UTF-8'>
        <title>原生委託事件</title>
        <style type='text/css'>
            ul{background:#f40}
            ul li {background: #ccc;}
        </style>
    </head>
    <body>
        <ul id='ul'>
            <li>11312</li>
            <li>23213</li>
            <li>33123</li>
        </ul>
        <button id='oBtn'>新增節點</button>
    </body>
    <script type='text/javascript'>
        var elm=document.getElementById('ul');
        elm.onclick=function(event){
            var eve=event||window.event;
            //獲取到使用者點選中的dom結構體
            var targer=event.target||event.srcElement;
            //targer.nodeName.toLowerCase()獲取到節點
            if(targer.nodeName.toLowerCase()=='li'){
                alert(targer.innerHTML);//獲取結構裡面的引數
            }   
        }
    </script>
</html>

3.委託事件存在的問題

如果從dom中新增節點會出現問題,使用getElementsByTagName先進行對li遍歷然後對遍歷過的li進行了事件繫結然後再生成新的li節點然後發現這些新增的節點會沒有綁到事件.

<!DOCTYPE html>
<html>
    <head>
        <meta charset='UTF-8'>
        <title>原生委託事件</title>
        <style type='text/css'>
            ul{background:#f40}
            ul li {background: #ccc;}
        </style>
    </head>
    <body>
        <ul id='ul'>
            <li>11312</li>
            <li>23213</li>
            <li>33123</li>
        </ul>
        <button id='oBtn'>新增節點</button>
    </body>
    <script type='text/javascript'>
        var elm=document.getElementById('ul');
        var oBtn=document.getElementById('oBtn');
        var val=0;
        //新增元素
        var  lis=elm.getElementsByTagName('li');
        for(var i=0;i<lis.length;i++){
            lis[i].onmouseover=function(){
                this.style.background='red';
            }
            lis[i].onmouseout=function(){
                this.style.background='blue';
            }
        }
        //新新增的節點沒觸發到滑鼠移動事件
        oBtn.onclick=function(){
            val++;
            var oLi=document.createElement('li');
            oLi.innerHTML=666+val;
            elm.appendChild(oLi);
        }
    </script>
</html>

3.1解決方法

1.給公共的事件起個方法名字,當誰想要用到它就呼叫這個公共方法名

<!DOCTYPE html>
<html>
    <head>
        <meta charset='UTF-8'>
        <title>原生委託事件</title>
        <style type='text/css'>
            ul{background:#f40}
            ul li {background: #ccc;}
        </style>
    </head>
    <body>
        <ul id='ul'>
            <li>11312</li>
            <li>23213</li>
            <li>33123</li>
        </ul>
        <button id='oBtn'>新增節點</button>
    </body>
    <script type='text/javascript'>
        var elm=document.getElementById('ul');
        var oBtn=document.getElementById('oBtn');
        var val=0;
        //新增元素
        var  lis=elm.getElementsByTagName('li');
        function hover(){
            for(var i=0;i<lis.length;i++){
                lis[i].onmouseover=function(){
                    this.style.background='red';
                }
                lis[i].onmouseout=function(){
                    this.style.background='blue';
                }
            }
        }
        //新新增的節點也觸發了滑鼠移動時的事件了
        oBtn.onclick=function(){
            val++;
            var oLi=document.createElement('li');
            oLi.innerHTML=666+val;
            elm.appendChild(oLi);
            hover();//老子呼叫hover方法了
        }
    </script>
</html>

2.將事件都變成一個個小小的功能模組自己專職去做自己的事情

<!DOCTYPE html>
<html>
    <head>
        <meta charset='UTF-8'>
        <title>原生委託事件</title>
        <style type='text/css'>
            ul{background:#f40}
            ul li {background: #ccc;}
        </style>
    </head>
    <body>
        <ul id='ul'>
            <li>11312</li>
            <li>23213</li>
            <li>33123</li>
        </ul>
        <button id='oBtn'>新增節點</button>
    </body>
    <script type='text/javascript'>
        var elm=document.getElementById('ul');
        var oBtn=document.getElementById('oBtn');
        var val=0;
        //新增元素
        var  lis=elm.getElementsByTagName('li');
        elm.onmouseover=function(event){
            var ev=event||window.event;
            var eve=ev.target||ev.srcElement;
            if(eve.nodeName.toLowerCase() == 'li'){
                eve.style.background='red';
            }
        }
        elm.onmouseout=function(event){
            var ev=event||window.event;
            var eve=ev.target||ev.srcElement;
            if(eve.nodeName.toLowerCase() == 'li'){
                eve.style.background='blue';
            }
        }
        //新新增的節點沒繫結委託
        oBtn.onclick=function(){
            val++;
            var oLi=document.createElement('li');
            oLi.innerHTML=666+val;
            elm.appendChild(oLi);

        }
    </script>
</html>

4.場景

適合用事件委託的事件:click,mousedown,mouseup,keydown,keyup,keypress。
不適合委託:focus,blur之類的,本身就沒用冒泡的特性

5.JQuery

1.on(繫結事件),off(用來移除事件繫結)
1.1on

function myHandler(event) {  
alert(event.data.foo);  
}  
$('p').on('click', {foo: 'bar'}, myHandler)

1.2off

$('body').off('click', 'p', foo);

2.live(方法為被選元素附加一個或多個事件處理程式,並規定當這些事件發生時執行的函式。)
地址:http://www.w3school.com.cn/jquery/event_live.asp
3.bind(同時繫結多個事件型別,同時繫結多個事件型別/處理程式,)
4.delegate(為了突破單一.bind()方法的侷限性,實現事件委託)

$('#info_table').delegate('td','click',function(){/*顯示更多資訊*/});

4.1 undelegate(移除delegate的繫結)
5.one(只執行一次)