javascript是事件驱动型语言。当用户在网页中进行某种操作时,就产生了一个“事件”(Event)。
事件几乎可以是任何事情:单击一个网页元素、拖动鼠标等均可视为事件。JavaScript是事件驱动的,当事件发生时,它可以对之做出响应。具体如何响应某个事件由编写的事件处理函数完成。
事件分为系统派发事件和自定义派发事件。
注意:
//document就是侦听派发的对象
//click就是这里的事件类型
document.addEventListener("click",clickHandler);
//div元素的继承为下:
//Object-->EventTarget-->Node-->Element-->HTMLElement-->HTMLDivElement
//EventTarget叫事件目标对象
var target=new EventTarget();
target.addEventListener("chilema",clickHandler);
//Event实例的对象叫事件对象
var evt=new Event("chilema");
evt.num=10;
target.dispatchEvent(evt);//派发事件
//
function clickHandler(e){
//e.type为派发的事件类型
console.log(e.type);
}
目的是使程序模块的可重用性、移植性大大增强。一个好的内聚模块应当恰好做一件事。
obj 和 obj1 互相调用,但是不相互影响,删除任意一个函数后,也不会报错。
// 高内聚低耦合
var obj={
a:function(){
document.addEventListener("b",this.b);
},
b:function(e){
var num=e.num+10;
var evt=new Event("a");
evt.num=num;
document.dispatchEvent(evt);
}
}
var obj1={
a:function(){
document.addEventListener("a",this.b);
var evt=new Event("b");
evt.num=2;
document.dispatchEvent(evt);
},
b:function(e){
console.log(e.num);//12
}
}
obj.a();
obj1.a();
事件冒泡(event bubbling),即事件开始时由最具体的元素(文档中嵌套层次最深的那个节点)接收,然后逐级向上传播到较为不具体的节点(文档)。即子标签发生事件后,向父级发送该事件,一直追溯到document。如:点击一个嵌套在 body中的button,则该button的onclick事件也会传递给body、document中,触发他们的onclick里触发的函数。
var div1 = document.getElementById("div1");
var div2 = document.getElementById("div2");
var div3 = document.getElementById("div3");
div1.addEventListener("click", clickHandler1);
div2.addEventListener("click", clickHandler2);
div3.addEventListener("click", clickHandler3);
function clickHandler1(e) {
console.log("div1")
}
function clickHandler2(e) {
console.log("div2")
}
function clickHandler3(e) {
console.log("div3")
}
当对子元素添加了事件侦听后,执行的时候会触发父元素相同类型的事件,此时需要阻止事件冒泡。
早期IE是没有捕获阶段的,只有冒泡,cancelBubble为阻止冒泡。后来的stopPropagaiton,既有阻止冒泡的功能,也有阻止捕获的功能,但如果译为阻止传播,那么跟cancel就是两个东西了,所以还是叫做阻止冒泡。阻止事件冒泡(传播)的方法是:
var div1 = document.getElementById("div1");
var div2 = document.getElementById("div2");
var div3 = document.getElementById("div3");
div1.addEventListener("click", clickHandler1);
div2.addEventListener("click", clickHandler2);
div3.addEventListener("click", clickHandler3);
function clickHandler1(e) {
e.stopPropagation();//阻止事件冒泡
// e.cancelBubble=true;//阻止事件冒泡 IE8一下浏览器
console.log("div1")
}
function clickHandler2(e) {
console.log("div2")
}
function clickHandler3(e) {
console.log("div3")
}
事件侦听添加(注册事件)占有内存的,尽量减少事件侦听的数量,将子元素的事件委托给父元素来执行,叫做事件委托。
当删除对象时,一定要将对象上的侦听事件移除,否则会造成内存泄露。
案例:点击 li ,让其子元素 ul 切换显示。
布局代码:
<ul id="menu">
<li>北京
<ul>
<li>海淀li>
<li>昌平
<ul>
<li>沙河li>
<li>回龙观li>
<li>天通苑li>
ul>
li>
<li>朝阳li>
<li>东城li>
ul>
li>
<li>河北li>
<li>天津li>
<li>河南li>
<li>山西li>
ul>
js代码:
var menu=document.querySelector("#menu");
//给最外层的ul侦听点击事件
menu.addEventListener("click",clickHandler);
function clickHandler(e){
//如果点击的不是li标签,直接退出
if(e.target.constructor!==HTMLLIElement)return;
//如果点击的li没有子元素,直接退出
if(!e.target.firstElementChild) return;
//阻止事件冒泡
e.stopPropagation();
//控制li下的ul显示隐藏
if(!e.target.bool) e.target.firstElementChild.style.display="none";
else e.target.firstElementChild.style.display="block";
e.target.bool=!e.target.bool;
}
//给body侦听点击事件,冒泡阶段执行
document.body.addEventListener("click", clickHandler);
//给body侦听点击事件,捕获阶段执行
document.body.addEventListener("click", clickHandler,true);
//给body侦听点击事件,只执行一次
document.body.addEventListener("click", clickHandler,{
once:true});
document.body.removeEventListener("click", clickHandler);
document.onclick=function(){
document.onclick=null;//移除事件侦听
console.log("a")
}
//事件会覆盖上面的事件
document.onclick=function(){
console.log("b");
}
document.addEventListener("click",clickHandler1);
document.addEventListener("click",clickHandler2);
function clickHandler1(e){
//移除事件侦听
document.removeEventListener("click",clickHandler1);
console.log("a");
}
function clickHandler2(e){
console.log("b")
}
// 事件匿名函数的不断迭代就会造成回调地狱
document.onclick=function(){
var bn=document.querySelector("button");
bn.onclick=function(){
console.log("aaa");
}
}
document.body.addEventListener("click", clickHandler);//冒泡阶段执行
document.body.addEventListener("click", clickHandler,true);//捕获阶段执行
document.attachEvent("onclick",clickHandler);//IE8及以下使用,其他版本和其他浏览器不支持
function clickHandler(e){
console.log("aaa");
document.detachEvent("onclick",clickHandler);//移除事件侦听
}
事件侦听和移除的兼容写法:
function addEvent(elem,type,eventHandler){
try{
elem.addEventListener(type,eventHandler);
}catch(e){
elem.attachEvent("on"+type,eventHandler);
}
}
function removeEvent(elem,type,eventHandler){
try{
elem.removeEventListener(type,eventHandler);
}catch(e){
elem.detachEvent("on"+type,eventHandler);
}
}
addEvent(document,"click",clickHandler);
function clickHandler(){
}