1,事件处理模型
以下就是事件处理模型例子的代码
<style>
.red{
width: 200px;
height: 200px;
background-color: red;
}
.green{
width: 150px;
height: 150px;
background-color: green;
}
.yellow{
width: 100px;
height: 100px;
background-color: yellow;
}
</style>
----------------------------------------
<div class = "red">
<div class = "green">
<div class = "yellow">
</div>
</div>
</div>
--------------------------------------------------------------------
<script>
var red = document.getElementsByClassName('red')[0];
var green = document.getElementsByClassName('green')[0];
var yellow = document.getElementsByClassName('yellow')[0];
red.addEventListener('click',function(){
console.log("red");
},false);
green.addEventListener('click',function(){
console.log("green");
},false);
yellow.addEventListener('click',function(){
console.log("yellow");
},false);
</script>
1,事件冒泡
html结构上(非视觉上)嵌套关系的元素,会存在事件冒泡的功能,即同一事件,自子元素冒泡向父元素。(结构上自底向上)
下层的DOM节点定义的事件处理函数,到了上层的节点如果还有和下层相同事件类型的事件处理函数,那么上层的事件处理函数也会执行。
2,事件捕获
html结构上(非视觉上)嵌套关系的元素,会存在事件捕获的功能,即同一事件,自父元素捕获至子元素(事件源元素)。(结构上自顶向下)
elem.addEventListener('type',fn,true);
第三个参数为true就是开启了事件捕获
IE没有捕获事件
事件捕获有chrome浏览器实现了,最新版本的火狐,opera也有,老版本没有
3,触发顺序,先捕获,后冒泡
-
同一个对象的同一个事件类型上面绑定了
一个
理函数只能遵循一种处理模型,就是说一个元素绑定了一个事件处理函数,那么这个事件处理函数要么就是事件冒泡的处理模型,要么就是事件捕获的处理模型。 -
同一个对象的同一个事件类型上面绑定了
两个
事件处理函数,一个是事件冒泡,一个是事件捕获,触发顺序就是先捕获再冒泡
。 -
解释触发顺序
1,
2,
4,focus,blur,change,submit,reset,select等事件不冒泡
2,取消冒泡事件
event.stopPropagation()–> W3C标准(IE9以下不支持)
event.cancelBubble = true -->IE独有
封装一个函数取消事件冒泡(兼容版)
function stopBubble(event) {
if (event.stopPropagation) {
event.stopPropagation();
} else {
event.cancelBubble = true;
}
}
3, 阻止默认事件
默认事件------> 表单提交,a标签跳转或者刷新页面,点击右键弹出菜单等
1. return false—>以句柄(elem.onXXX = fn)的方式绑定的事件才生效
2. event.prevetDefault()—>W3C标注,IE9以下不兼容
3. event.returnValue = false—>兼容IE
4 .封装阻止默认事件的函数(兼容版)
function cancelHandler(event) {
if(event.prevetDefault){
event.prevetDefault();
}else{
event.returnValue = false;//包括了兼容IE的,也包括了以句柄形式的return false;
}
}
举个例子:阻止a标签默认跳转或者刷新页面,阻止点击右键默认弹出菜单
阻止a标签默认跳转或者刷新页面
//第一种方式
<a href="javascript:void()">demo</a>
//第一种方式
var a = document.getElementsByTagName('a')[0];
a.onclick = function(){
return false;
}
阻止点击右键默认弹出菜单
//第一种方式
document.oncontextmenu = function(){
console.log('a');
return false;
}
//第二种方式
document.oncontextmenu = function (e) {
console.log('a');
cancelHandler(e);
}
function cancelHandler(event) {
if(event.prevetDefault){
event.prevetDefault();
}else{
event.returnValue = false;
}
}
4, 综合2,3
JS-阻断事件传播:
1:stopPropagation(原生js上的):
2:preventDefault
3:stopImmediatePropagation(jquery上的)stopImmediatePropagation做了两件事情:
- 第一件事:阻止 绑定在事件触发元素的 其他同类事件的callback的运行。
- 第二件事,阻止事件传播到父元素,这跟stopPropagation的作用是一样的
- stopImmediatePropagation();这个函数用于阻断同一element的事件传播。 例如一个element上定义了多个listener,如果其中一个调用这个方法后面的listener则都不会执行。
事件对象
1,事件对象:在触发DOM上的某个事件的时候,会产生一个事件对象event,而在这个对象当中会包含着所有与事件有关的信息。(事件对象的属性详解:(https://blog.csdn.net/weixin_43623871/article/details/88894094))
2,事件对象的兼容写法:
var event =e || window.event (用于IE);
3,事件对象其中有两个信息,我们最为常用,分别是type和target:
1. type:事件的类型,如onlick中的click;
2. srcElement/target:事件源,就是发生事件的元素(dom元素);
事件源对象
event.target(火狐只有这个)
event.srcElement(IE只有这个)
chrome这两个都有。
<div class = "red"></div>
-----------------------------
var red = document.getElementsByClassName('red')[0];
red.onclick = function(e){
var event = e || window.event;
var target = event.target || event.srcElement;
console.log(event);
console.log(target);//求事件源对象
}
事件对象和事件源对象的兼容性写法
function(e){
var event = e || window.event;
var target = event.target || event.srcElement;
}
事件委托
要求:点击每一个li ,打印出对应li里面的内容
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
<li>7</li>
<li>8</li>
<li>9</li>
<li>10</li>
</ul>
-----------------------------------------------
1,土办法: 给每一个li绑定点击事件:
var li = document.getElementsByTagName('li');
var len = li.length;
for(var i = 0; i < len; i++) {
li[i].onclick = function (){
console.log(this.innerText);
}
}
2,事件委托办法:给父元素ul一个人绑定点击事件,利用事件冒泡和事件源对象处理 ,
因为每点击一个li,该li就会成为事件源对象,因为li始终在ul里面。
var ul = document.getElementsByTagName('ul')[0];
ul.onclick = function (e) {
var event = e || window.event;
var target = event.target || event.srcElement;
console.log(target.innerHTML);
}
利用事件冒泡和事件源对象进行处理
优点:
- 性能:不需要循环所有的元素一个个绑定事件(题目如果是一百万个li,上面的土方法就会特别憨)
- 灵活:当有新的子元素添加将进来时不需要重新绑定事件(当有新的li的时候,土方法就要重新给新的li绑定点击事件,但是利用事件委托就可以不用管,因为你再加多少,它总是在ul里面,点击的时候它就会是target)