Распространение событий

Когда мы нажимаем на какой-либо элемент на станице и генерируется событие нажатия, то это событие может распространяться от элемента к элементу. Например, если мы нажимаем на блок div, то также мы нажимаем и на элемент body, в котором блок div находится. То есть происходит распространение события.

Есть несколько форм распространения событий:

  • Восходящие: событие распространяется вверх по дереву DOM от дочерних узлов к родительским
  • Нисходящие: событие распространяется вниз по дереву DOM от родительских узлов к дочерним, пока не достигнет того элемента, на котором это событие и возникло
  • Восходящие события

    Рассмотрим восходящие (bubbling) события, которые распространяются в верх по дереву DOM. Допустим, у нас есть следующая веб-страница:

    	<!DOCTYPE html>
    	<html>
    	<head>
    	<meta charset="utf-8" />
    	<style>
    	
    	#blueRect{
    	width:100px;
    	height:100px;
    	background-color:blue;
    	}
    	#redRect{
    	width:50px;
    	height:50px;
    	background-color:blue;
    	}
    	
    	</style>
    	</head>
    	<body>
    	<div id="rect" </div>
    	<script>
    	
    	var redRect = document.getElementById("redRect");
    	redRect.addEventListener("click", function(){
    	console.log("Событие на redRect");
    	});
    	
    	var blueRect = document.getElementById("blueRect");
    	blueRect.addEventListener("click", function(){
    	console.log("Событие на blueRect");
    	});
    	
    	document.body.addEventListener("click", function(){
    	console.log("Событие на body");
    	});
    	
    	</script>
    	</body>
    	</html>
    	
    Test.запустить код
    Если мы нажмем на вложенный div, то событие пойдет к родительскому элементу div и далее к элементу body. Надо сказать, что подобное поведение не всегда является желательным. И в этом случае мы можем остановить распространение событие с помощью метода stopPropagation() объекта Event:
    var redRect = document.getElementById("redRect");
    redRect.addEventListener("click", function(e){
    	console.log("Событие на redRect");
    	e.stopPropagation();
    });
    
    И в результате нажатия событие будет обработано только обработчиком для redRect.

    Нисходящие события

    События также могут быть нисходящими (capturing). Для их использования в метод addEventListener() в качестве третьего необязательного параметра передается логическое значение true или false, которое указывает, будет ли событие нисходящим. По умолчанию все события восходящие.

    Возьмем ту же веб-станицу, только изменим ее код javascript:

    var redRect = document.getElementById("redRect");
    redRect.addEventListener("click", function(){
    	console.log("Событие на redRect");
    }, true);
    
    var blueRect = document.getElementById("blueRect");
    blueRect.addEventListener("click", function(){
    	console.log("Событие на blueRect");
    }, true);
    
    document.body.addEventListener("click", function(){
    	console.log("Событие на body");
    }, true);
    
    Теперь события будут распространяться в обратном порядке. Test.запустить код