1. 程式人生 > >js事件監聽:addEventListener() 與 移除事件:removeEventListener()

js事件監聽:addEventListener() 與 移除事件:removeEventListener()

說事件繫結得先說事件流

事件流

冒泡型事件流:事件的傳播是從最特定事件目標到最不特定的事件目標。即從DOM樹的葉子到根。【推薦】

捕獲型事件流:事件的傳播是從最不特定事件目標到最特定的事件目標。即從DOM樹的根到葉子。

DOM標準採用捕獲+冒泡。兩種事件流都會觸發DOM的所有物件,從document物件開始,也在document物件結束。

來個例子看一下吧!

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
<div id="myDiv">Click me!</div>
</body>
</html>

當點選了div時事件流走向,

在冒泡型事件流中click事件傳播順序為:<div> =》<body> =》<html> =》document

在捕獲型事件流中click事件傳播順序為:document =》<html> =》<body> =》<div>

這裡之所以說冒泡,並不是檢視上的冒泡,而是結構上的冒泡。這裡要弄清楚了,就算在檢視上div是獨立的,但他的在html結構

結構上依舊是被body所包裹。而冒泡是由內而外向上冒泡。

懂了冒泡之後,捕獲就好理解了,就是反向的事件流。由外而內。

事件處理

以上明白了事件流,現在說說怎樣處理事件。

    HTML事件處理:

 直接在標籤內繫結事件,例如:<button onclick="something()"></button>

這裡直接將js內something函式繫結到button上。

缺點:

1.一個方法需要多次引用,而且不符合 行為、結構、樣式 相分離的原則。

2.當js的函式名更改,html標籤內的方法也需要更改。

     DOM 0級事件處理:

在<script>中獲取dom元素繫結事件,例如:btn.onclick = function () {}

0級事件處理的較HTML事件處理的有點很明顯,他完全寫在<script>內,符合 行為、結構、樣式

相分離的原則。還可以選出DOM元素集合通過for迴圈統一操作。

缺點:每個DOM元素只能繫結一個同類事件。例如繫結onclick,當你想在繫結onclick會發現他被覆蓋了。

     DOM 2級事件處理(事件監聽)

addEventListener("事件名" , "事件處理函式" , "布林值");

false 事件冒泡           true   事件捕獲    

優點相比前兩個就多了。可以選擇是事件流。可繫結多個同類事件。事件名可以組成字串。

到今天的主題了~~

addEventListener() 和 removeEventListener()

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>addEventListener</title>
    <script type="text/javascript" src="js/jquery-3.0.0.js"></script>
    <style type="text/css">
        #content{
            width: 100px;
            height: 100px;
            background: #f9f;
        }
    </style>
</head>
<body>
    <div id="content"></div>
    <script type="text/javascript">
        //addEventListener 用於向指定元素新增事件控制代碼
        //可以向一個元素新增多次點選事件,後一個點選事件不會覆蓋前一個點選事件

        var content = document.getElementById("content");
        content.addEventListener("click",function(){
            
            console.log("11");
        },false)
        content.addEventListener("click",function(){
            
            console.log("22");
        },false)
        content.addEventListener("mouseenter",add,false);
        function add(){
            console.log("成哥沒我帥");
        }
        //由於成哥並不這麼認為,一再用自身的權勢讓我更改這個事實,所以下面我需要再移出這個事件
        content.removeEventListener("mouseenter",add,false);
    </script>
</body>
</html>

注意:removeEventListener() 不能移除匿名函式,像上面add()這種是可以的。removeEventListener需要知道你需要移出的是哪個事件處理函式。匿名函式丟棄了自身函式名,所以移出不了。

下面再講一些補充吧。

阻止預設事件preventDefault()


document.body.addEventListener('touchmove', function (event) {
    event.preventDefault();
},false);

阻止事件冒泡stopPropagation()

解釋:只點擊了button,但是包含button的div也執行了,這屬於事件冒泡,事件逐級向上傳遞,傳給了div,有時並不需要事件冒泡,可以通過stopPropagation()  

<div id="div">
    <button id="btn">按鈕</button>
</div>
<script>
        document.getElementById("btn").addEventListener("click",showType);
        document.getElementById("div").addEventListener("click",showDiv);
        function showType(event){
            alert(event.type);
            event.stopPropagation();
        }
 
        function showDiv(){
            alert("div");
        }
</script>

事件代理

這裡歸類可能沒歸好,也看看吧

傳統的事件處理中,需要為每個元素新增事件處理器。js事件代理則是一種簡單有效的技巧,通過它可以把事件處理器新增到一個父級元素上,從而避免把事件處理器新增到多個子級元素上。

事件代理的原理用到的就是事件冒泡和目標元素,把事件處理器新增到父元素,等待子元素事件冒泡,並且父元素能夠通過target(IE為srcElement)判斷是哪個子元素,從而做相應處理

 傳統事件處理,為每個元素新增事件處理器,程式碼如下:

<!DOCTYPE html>
<html lang="zh">
<head>
	<meta charset="UTF-8" />
	<meta name="viewport" content="width=device-width, initial-scale=1.0" />
	<meta http-equiv="X-UA-Compatible" content="ie=edge" />
	<title>Document</title>
</head>
<body>
	<ul id="color-list">
		<li>red</li>
		<li>orange</li>
		<li>yellow</li>
		<li>green</li>
		<li>blue</li>
		<li>indigo</li>
		<li>purple</li>
	</ul>
	<script>
	(function(){
	    var colorList=document.getElementById("color-list");
	    var colors=colorList.getElementsByTagName("li");
	    for(var i=0;i<colors.length;i++)
	    {
	        colors[i].addEventListener('click',showColor,false);
	    };
	    function showColor(e)
	    {
	        e=e||window.event;
	        var targetElement=e.target||e.srcElement;
	        alert(targetElement.innerHTML);
	    }
	})();
	</script>

</body>
</html>

事件代理的處理方式,程式碼如下:

<!DOCTYPE html>
<html lang="zh">
<head>
	<meta charset="UTF-8" />
	<meta name="viewport" content="width=device-width, initial-scale=1.0" />
	<meta http-equiv="X-UA-Compatible" content="ie=edge" />
	<title>Document</title>
</head>
<body>
	<ul id="color-list">
		<li>red</li>
		<li>orange</li>
		<li>yellow</li>
		<li>green</li>
		<li>blue</li>
		<li>indigo</li>
		<li>purple</li>
	</ul>
	<script>
	(function(){
	    var colorList=document.getElementById("color-list");
	    colorList.addEventListener('click',showColor,false);
	    function showColor (e) {
	        e=e||window.event;
	        var targetElement=e.target||e.srcElement;
	        if(targetElement.nodeName.toLowerCase()==="li"){
	        alert(targetElement.innerHTML);
	        }
	    }
	})();
	</script>

</body>
</html>

事件代理的好處

 總結一下事件代理的好處:

  • 將多個事件處理器減少到一個,因為事件處理器要駐留記憶體,這樣就提高了效能。想象如果有一個100行的表格,對比傳統的為每個單元格繫結事件處理器的方式和事件代理(即table上新增一個事件處理器),不難得出結論,事件代理確實避免了一些潛在的風險,提高了效能。
  • DOM更新無需重新繫結事件處理器,因為事件代理對不同子元素可採用不同處理方法。如果新增其他子元素(a,span,div等),直接修改事件代理的事件處理函式即可,不需要重新繫結處理器,不需要再次迴圈遍歷。

 而代理事件需要注意的是事件冒泡, 例如:Li裡有span,這時我只想操作Li那我就要用到阻止冒泡了。

好了,就到這裡吧。本次分享到這裡就結束了,作者自身的技術不是很好,如果有哪裡誤導了大家,請留言提醒我一下。

並不是很全,不過夠用了,裡面沒有提及觸屏事件等等。