事件的委派
在很多需求中,通常元素是动态创建添加到一个父元素中的,这时候我们点击新增的元素是没有反应的
<script type="text/javascript"> window.onload = function(){ var u1 = document.getElementById("u1"); var btn01 = document.getElementById("btn01"); btn01.onclick = function(){ var li = document.createElement("li"); //创建一个li li.innerHTML = "<a href='javascript:;' class='link'>新建的超链接</a>"; u1.appendChild(li); //点击按钮以后添加超链接,将li添加到ul中 }; /* * 为每一个超链接都绑定一个单击响应函数 * 这里我们为每一个超链接都绑定了一个单击响应函数,这种操作比较麻烦, * 而且这些操作只能为已有的超链接设置事件,而新添加的超链接必须重新绑定 */ //获取所有的a,这样其实后面新增的li点击没效果 var allA = document.getElementsByTagName("a"); //遍历 for(var i=0 ; i<allA.length ; i++){ allA[i].onclick = function(){ alert("我是a的单击响应函数!!!"); }; } }; </script> </head> <body> <button id="btn01">添加超链接</button> <ul id="u1" style="background-color: #bfa;"> <li> <p>我是p元素</p> </li> <li><a href="javascript:;" class="link">超链接一</a></li> <li><a href="javascript:;" class="link">超链接二</a></li> <li><a href="javascript:;" class="link">超链接三</a></li> </ul> </body>
点击新建的超链接,不会有任何反应,没有触发到点击事件。这时候我们希望,只绑定一次事件,即可应用到多个的元素上,即使元素是后添加的
可以尝试将其绑定给元素的共同的祖先元素
指将事件统一绑定给元素的共同的祖先元素,这样当后代元素上的事件触发时,会一直冒泡到祖先元素(这个就是冒泡的好处),从而通过祖先元素的响应函数来处理事件
事件委派是利用了冒泡,通过委派可以减少事件绑定的次数,提高程序的性能
<script type="text/javascript"> window.onload = function(){ var u1 = document.getElementById("u1"); var btn01 = document.getElementById("btn01"); btn01.onclick = function(){ var li = document.createElement("li"); //创建一个li li.innerHTML = "<a href='javascript:;' class='link'>新建的超链接</a>"; u1.appendChild(li); //点击按钮以后添加超链接,将li添加到ul中 }; // 为ul绑定一个单击响应函数 u1.onclick = function(event){ event = event || window.event; //如果触发事件的对象是我们期望的元素,则执行否则不执行 if(event.target.className == "link"){ console.log(this) // this是ul这个元素 console.log(event.target) // event中的target表示的触发事件的对象 alert("我是ul的单击响应函数"); } }; }; </script> </head> <body> <button id="btn01">添加超链接</button> <ul id="u1" style="background-color: #bfa;"> <li> <p>我是p元素</p> </li> <li><a href="javascript:;" class="link">超链接一</a></li> <li><a href="javascript:;" class="link">超链接二</a></li> <li><a href="javascript:;" class="link">超链接三</a></li> </ul> </body>
这时候点击新建的超链接就有效果了
事件的绑定
使用 对象.事件 = 函数 的形式绑定响应函数,它只能同时为一个元素的一个事件绑定一个响应函数,不能绑定多个,如果绑定了多个,则后边会覆盖掉前边的
<body> <button id="btn01">点我一下</button> </body> </html> <script type="text/javascript"> window.onload = function(){ var btn01 = document.getElementById("btn01"); //为btn01绑定一个单击响应函数 btn01.onclick = function(){ alert(1); }; //为btn01绑定第二个响应函数 btn01.onclick = function(){ alert(2); }; }; </script>
执行结果第二个绑定的响应函数覆盖了第一个绑定的函数,使用addEventListener()可以同时为一个元素的相同事件同时绑定多个响应函数
这样当事件被触发时,响应函数将会按照函数的绑定顺序执行,addEventListener(),通过这个方法也可以为元素绑定响应函数
参数:第一个参数:事件的字符串,不要on。第二个参数:回调函数,当事件触发时该函数会被调用。第三个参数:是否在捕获阶段触发事件,需要一个布尔值,一般都传false
<body> <button id="btn01">点我一下</button> </body> </html> <script type="text/javascript"> window.onload = function(){ var btn01 = document.getElementById("btn01"); btn01.addEventListener("click",function(){ alert(1); },false); btn01.addEventListener("click",function(){ alert(2); },false); }; </script>
执行结果可以看到,两个绑定的响应函数都触发了,这个方法不支持IE8及以下的浏览器,但可以使用attachEvent()方法
这个方法也可以同时为一个事件绑定多个处理函数,不同的是它是后绑定先执行,执行顺序和addEventListener()相反
参数:第一个参数:事件的字符串,要on。第二个参数:回调函数
<body> <button id="btn01">点我一下</button> </body> </html> <script type="text/javascript"> window.onload = function(){ var btn01 = document.getElementById("btn01"); btn01.attachEvent("onclick",function(){ alert(1); }); btn01.attachEvent("onclick",function(){ alert(2); }); btn01.attachEvent("onclick",function(){ alert(3); }); }; </script>
执行结果是先执行了第三个绑定的响应函数,依次第二个,第一个。执行顺序和addEventListener()相反
在以上两个方法中,的this指向不一样。addEventListener()中的this,是绑定事件的对象
<body> <button id="btn01">点我一下</button> </body> </html> <script type="text/javascript"> window.onload = function(){ var btn01 = document.getElementById("btn01"); btn01.addEventListener("click",function(){ console.log(this); // this是绑定事件的对象:<button id="btn01">点我一下</button> },false); }; </script>
attachEvent()中的this,是window
<body> <button id="btn01">点我一下</button> </body> </html> <script type="text/javascript"> window.onload = function(){ var btn01 = document.getElementById("btn01"); btn01.attachEvent("onclick",function(){ console.log(this); //this是window }); }; </script>
那么我们可以写一个方法来兼容这两种方法:先判断是否支持addEventListener方法,如果支持就执行这种方式,如果不支持就执行attachEvent方法,并且统一this的指向
<body> <button id="btn01">点我一下</button> </body> </html> <script type="text/javascript"> window.onload = function(){ var btn01 = document.getElementById("btn01"); bind(btn01 , "click" , function(){ console.log(this); }); }; /* * 参数: * obj 要绑定事件的对象 * eventStr 事件的字符串(不要on) * callback 回调函数 */ function bind(obj , eventStr , callback){ if(obj.addEventListener){ //大部分浏览器兼容的方式 obj.addEventListener(eventStr , callback , false); }else{ /* * this是谁由调用方式决定 * callback.call(obj) */ //IE8及以下 obj.attachEvent("on"+eventStr , function(){ // 在匿名函数中调用回调函数 callback.call(obj); }); } } </script>