由浅入深JavaScript11进阶-事件1
什么是事件
JavaScript与HTML之间是通过事件来交互。
事件,就是文档或浏览器窗口中发生的一些特定的交互瞬间。
事件一般分为DOM事件(文档对象模型事件)和BOM事件(浏览器对象模型事件)。
事件流
事件流描述了在页面中接受事件的顺序。
比如:在页面里有三个嵌套的DIV,最大的DIV在下面,最小的在上面
eg:
<script type="text/javascript">
window.onload = function(){
document.getElementById('div1').onclick = function(){
alert('div1');
}
document.getElementById('div2').onclick = function(){
alert('div2');
}
document.getElementById('div3').onclick = function(){
alert('div3');
}
}
</script>
<div id="div3" style="width:900px;height:900px;background:red;z-index: 1;" >
<div id="div2" style="background:green;width:600px;height:600px;z-index: 2;">
<div id="div1" style="background:yellow;width:300px;height:300px;z-index: 3;">
</div>
</div>
</div>
如果我们点击div1那么事件该怎么算呢?
点击了div1,事实上也点击了div2,点击了div3。
会依次弹出alert('div3'),alert('div2'),alert('div1');
可是我们的本意是只点击div3,这就需要事件冒泡了。
事件冒泡
在IE中事件流被称为时间冒泡:事件由最先直接的元素接受然后逐级向上传递,
直到html-document。
如图:

事件处理程序
什么是事件处理程序,说白了就是响应事件的的函数。
比如,发生了click点击事件那么onclick就是事件处理程序。
比如,发生鼠标移动mousemove事件那么onmousemove就是事件处理程序
事件捆绑
将事件当做HTML属性,捆绑在HTML元素上称之为事件捆绑。
有时候也叫行间事件或HTML级事件处理程序
但是我们不推荐使用行间事件,这是因为行间事件有三个弊端。
弊端一:在html元素上捆绑了JavaScript事件后,这个值应当是
JavaScript值,因此不许与未经转义的HTML语法字符。比如,&
"",<,>。经转义分别使用:&,",<,>.
eg:
<input type="button" value="点击" onclick="alert(" hello ")" />
当然我们也可以在行间事件中引用定义好的函数。只需事件的值处写上函数名。
弊端二:
eg:
<input type="button" value="点击" onclick="showName('js')" />
ddddddddddddddddddddd
ddddddddddddddddddddd
ddddddddddddddddddddd
ddddddddddddddddddddd
1万行其他元素需要渲染
<script>
function showName(name){
alert(name);
}
</script>
上述例子,按钮添加行间事件,事件独立,按钮上是调用函数,并传入参数。但是这样会有一些瑕疵。
我们试想一下。如果把JavaScript代码放到最下面,而中间又有很多元素需要渲染,那么
当用户点击了按钮(手速快@[email protected]),可能还未执行到函数处,解释器会报错误。
当然这个解决办法也有很多,移动js位置,或使用try块都可以。但是行间事件
最大的弊端其实是耦合。
弊端三:行间事件将交互和表现混在一起,耦合严重,改js代码需要改HTML代码。
现代web前端我们讲,结构(HTML),表现(CSS),行为(js)分离。
DOM0级事件处理程序
Dom0级事件处理程序是最传统的事件处理方式,将一个函数
赋值给一个事件处理程序属性上。每个元素都有自己的事件处理属性。
这些属性通常全小写。
比如:btn.onclick = function(){}
将一个匿名函数绑定到 元素btn的事件处理程序的属性onclick上。
使用DOM0级事件处理程序,this指代事件发生的对象。
eg:
<script>
window.onload = function(){
var btn1 = document.getElementById('btn1');
btn1.onclick = function(){
alert('dom0级时间处理程序');
alert(this.value);//按钮
}
}
</script>
</head>
<body>
<input type="button" value="按钮" id="btn1"/>
</body>
DOM2级事件处理程序
使用条件IE9+
在DOM2级事件里定义了两个新方法。
addEventListener,removeEventListener。其好处是可以添加多个事件处理程序。
执行顺序为顺序执行。
其中this与DOM0级传统方式一致,也是指事件发生的对象。
addEventListener为添加事件,里面有三个参数,第一个参数为事件名称,
第二个参数为处理程序,第三个参数一般为false表示在事件冒泡阶段处理程序。
addEventListener('click',function(){},false);
亦可以
function showName(){};
addEventListener('click',showName,false);
其区别在于前者不能够取消事件,后者可以取消事件。
因为,removeEventListener('click',showName,false);
取消事件需要名字,前者的事件添加是一个匿名函数,没有函数名字,没法取消。
eg:
同一元素添加同一事件多个处理程序,并且两种处理方式。
以及删除事件。
<script>
window.onload = function(){
function showName(){
alert(this.id);//btn1
}
var btn1 = document.getElementById('btn1');
btn1.addEventListener('click',function(){
alert(this.id);//btn1
},false);
btn1.addEventListener('click',showName,false);
btn1.removeEventListener('click',function(){//无效
alert(this.id);
},false);
btn1.removeEventListener('click',showName,false);//有效
}
</script>
</head>
<body>
<input type="button" id="btn1" value="按钮" />
</body>
最后弹出btn1一次。
IE事件处理程序
只支持IE浏览器并且是5-10。最新的11也不支持
IE时间处理程序使用attachEvent和detachEvent两个函数。
与DOM2级事件处理程序相比,attachEvent和detachEvent只有两个参数,
事件名称,事件函数。由于IE是事件流只支持事件添加到冒泡阶段,所以
省略了最后一个参数,此外,函数名称加on,比如onclick
attchEvent('onclick',function(){});
也可以
attchEvent('onclick',showName);
区别在于前者是匿名函数无法删除事件。后者可以。
还需要注意的是,事件处理程序在全局作用域中运行,this指代window
eg:
<script>
window.onload = function(){
function showName(){
alert(this);//;window
}
var btn1 = document.getElementById('btn1');
btn1.attachEvent('onclick',function(){
alert(this);//window
});
btn1.attachEvent('onclick',showName);
btn1.detachEvent('onclick',function(){//无效
alert(this);
});
btn1.detachEvent('onclick',showName);//有效
}
</script>
JavaScript与HTML之间是通过事件来交互。
事件,就是文档或浏览器窗口中发生的一些特定的交互瞬间。
事件一般分为DOM事件(文档对象模型事件)和BOM事件(浏览器对象模型事件)。
事件流
事件流描述了在页面中接受事件的顺序。
比如:在页面里有三个嵌套的DIV,最大的DIV在下面,最小的在上面
eg:
<script type="text/javascript">
window.onload = function(){
document.getElementById('div1').onclick = function(){
alert('div1');
}
document.getElementById('div2').onclick = function(){
alert('div2');
}
document.getElementById('div3').onclick = function(){
alert('div3');
}
}
</script>
<div id="div3" style="width:900px;height:900px;background:red;z-index: 1;" >
<div id="div2" style="background:green;width:600px;height:600px;z-index: 2;">
<div id="div1" style="background:yellow;width:300px;height:300px;z-index: 3;">
</div>
</div>
</div>
如果我们点击div1那么事件该怎么算呢?
点击了div1,事实上也点击了div2,点击了div3。
会依次弹出alert('div3'),alert('div2'),alert('div1');
可是我们的本意是只点击div3,这就需要事件冒泡了。
事件冒泡
在IE中事件流被称为时间冒泡:事件由最先直接的元素接受然后逐级向上传递,
直到html-document。
如图:
事件处理程序
什么是事件处理程序,说白了就是响应事件的的函数。
比如,发生了click点击事件那么onclick就是事件处理程序。
比如,发生鼠标移动mousemove事件那么onmousemove就是事件处理程序
事件捆绑
将事件当做HTML属性,捆绑在HTML元素上称之为事件捆绑。
有时候也叫行间事件或HTML级事件处理程序
但是我们不推荐使用行间事件,这是因为行间事件有三个弊端。
弊端一:在html元素上捆绑了JavaScript事件后,这个值应当是
JavaScript值,因此不许与未经转义的HTML语法字符。比如,&
"",<,>。经转义分别使用:&,",<,>.
eg:
<input type="button" value="点击" onclick="alert(" hello ")" />
当然我们也可以在行间事件中引用定义好的函数。只需事件的值处写上函数名。
弊端二:
eg:
<input type="button" value="点击" onclick="showName('js')" />
ddddddddddddddddddddd
ddddddddddddddddddddd
ddddddddddddddddddddd
ddddddddddddddddddddd
1万行其他元素需要渲染
<script>
function showName(name){
alert(name);
}
</script>
上述例子,按钮添加行间事件,事件独立,按钮上是调用函数,并传入参数。但是这样会有一些瑕疵。
我们试想一下。如果把JavaScript代码放到最下面,而中间又有很多元素需要渲染,那么
当用户点击了按钮(手速快@[email protected]),可能还未执行到函数处,解释器会报错误。
当然这个解决办法也有很多,移动js位置,或使用try块都可以。但是行间事件
最大的弊端其实是耦合。
弊端三:行间事件将交互和表现混在一起,耦合严重,改js代码需要改HTML代码。
现代web前端我们讲,结构(HTML),表现(CSS),行为(js)分离。
DOM0级事件处理程序
Dom0级事件处理程序是最传统的事件处理方式,将一个函数
赋值给一个事件处理程序属性上。每个元素都有自己的事件处理属性。
这些属性通常全小写。
比如:btn.onclick = function(){}
将一个匿名函数绑定到 元素btn的事件处理程序的属性onclick上。
使用DOM0级事件处理程序,this指代事件发生的对象。
eg:
<script>
window.onload = function(){
var btn1 = document.getElementById('btn1');
btn1.onclick = function(){
alert('dom0级时间处理程序');
alert(this.value);//按钮
}
}
</script>
</head>
<body>
<input type="button" value="按钮" id="btn1"/>
</body>
DOM2级事件处理程序
使用条件IE9+
在DOM2级事件里定义了两个新方法。
addEventListener,removeEventListener。其好处是可以添加多个事件处理程序。
执行顺序为顺序执行。
其中this与DOM0级传统方式一致,也是指事件发生的对象。
addEventListener为添加事件,里面有三个参数,第一个参数为事件名称,
第二个参数为处理程序,第三个参数一般为false表示在事件冒泡阶段处理程序。
addEventListener('click',function(){},false);
亦可以
function showName(){};
addEventListener('click',showName,false);
其区别在于前者不能够取消事件,后者可以取消事件。
因为,removeEventListener('click',showName,false);
取消事件需要名字,前者的事件添加是一个匿名函数,没有函数名字,没法取消。
eg:
同一元素添加同一事件多个处理程序,并且两种处理方式。
以及删除事件。
<script>
window.onload = function(){
function showName(){
alert(this.id);//btn1
}
var btn1 = document.getElementById('btn1');
btn1.addEventListener('click',function(){
alert(this.id);//btn1
},false);
btn1.addEventListener('click',showName,false);
btn1.removeEventListener('click',function(){//无效
alert(this.id);
},false);
btn1.removeEventListener('click',showName,false);//有效
}
</script>
</head>
<body>
<input type="button" id="btn1" value="按钮" />
</body>
最后弹出btn1一次。
IE事件处理程序
只支持IE浏览器并且是5-10。最新的11也不支持
IE时间处理程序使用attachEvent和detachEvent两个函数。
与DOM2级事件处理程序相比,attachEvent和detachEvent只有两个参数,
事件名称,事件函数。由于IE是事件流只支持事件添加到冒泡阶段,所以
省略了最后一个参数,此外,函数名称加on,比如onclick
attchEvent('onclick',function(){});
也可以
attchEvent('onclick',showName);
区别在于前者是匿名函数无法删除事件。后者可以。
还需要注意的是,事件处理程序在全局作用域中运行,this指代window
eg:
<script>
window.onload = function(){
function showName(){
alert(this);//;window
}
var btn1 = document.getElementById('btn1');
btn1.attachEvent('onclick',function(){
alert(this);//window
});
btn1.attachEvent('onclick',showName);
btn1.detachEvent('onclick',function(){//无效
alert(this);
});
btn1.detachEvent('onclick',showName);//有效
}
</script>
总结:具体用哪一种事件处理程序,大家根据实际情况来选择
说在最后的话:
本博会开一个JS专栏:《大神前端:JavaScript板块》长期更新,由浅入深带大家系统的学习JavaScript,
做出多彩的JS特效。
如果对你有用就关注一下专栏吧,我会不断的更新,后期还有其他版块。
http://blog.****.net/column/details/15918.html
想深入,系统全面的学习JS,博友们可以在****搜索我的课程《多彩JavaScript》@[email protected]。
http://edu.****.net/course/detail/5619
限于文章篇幅原因,这里仅仅介绍冰山一角。由于笔者的水平有限,编写时间也很仓促,
文中难免会出现一些错误或者不准确的地方,不妥之处恳请读者批评指正