js事件与事件绑定

文章目录

    • 一、行内绑定
    • 二、动态绑定
    • 三、事件监听
    • 四、js中事件流模型
      • (一)事件冒泡
      • (二)事件捕获
      • (三)DOM事件流
    • 五、事件委托(事件代理)
    • 六、JS中的事件
      • (一)鼠标事件
      • (二)键盘事件
      • (三)对象事件
      • (四)表单事件
      • (五)拖动事件
      • (六)多媒体事件
      • (七)动画事件
      • (八)过度事件

js绑定事件的方法

  1. 行内绑定(HTML标签绑定)
  2. 动态绑定(js代码中DOM绑定)
  3. 事件监听(监听函数)

js事件绑定模型

  1. DOM0事件模型(行内绑定和动态绑定)
  2. DOM2事件模型(事件监听绑定)

一、行内绑定

为HTML元素添加事件属性

//html
<button onclick="func()">按钮</button>

//script
function func() {
     
  //...
}
function funb() {
     
  //...
}

<button onclick="func()" onclick="funb()">按钮</button>
//绑定两个onclick事件,只会触发前一个

<button onclick="func(),funb()">按钮</button>
//一个onclick事件绑定两个方法,两个方法都会被触发
  • 缺点:不符合W3C中关于内容和行为分离的基本规范;一旦绑定无法取消

二、动态绑定

通过js选取DOM节点,添加该节点的事件属性

//HTML
<button id="btn1">按钮</button>

//script
document.getElementById("btn1").onclick=func
document.getElementById("btn1").onclick=funb
//同时绑定两个事件,只能触发最后的一个(funb)

  • 优点:使js代码与HTML标签分离,文档结构清晰,便于管理和开发

  • **缺点:**同一个节点只能添加一次同类型事件,如果添加多次,最后一个生效;一旦绑定无法取消

三、事件监听

addEventListener()attachEvent() 来绑定事件监听函数。

element.addEventListener(event, function, useCapture)
element.attachEvent(eventName,handle)

element:指定元素

addEventListener() 方法用于向指定元素添加事件

event:指定事件名,不需要on前缀

function:事件触发执行的函数

useCapture:指定事件是否在捕获或冒泡阶段执行(true:捕获;false(默认):冒泡)

//HTML
<button id="btn1">按钮</button>

//script
document.getElementById("btn1").addEventListener("click",func)
document.getElementById("btn1").addEventListener("click",funb)
//两个事件都能触发,顺序是func -> funb

document.getElementById("btn1").attachEvent("onclick",func)
document.getElementById("btn1").attachEvent("onclick",funb)
//触发顺序funb -> func

//移除事件
document.getElementById("btn1").removeEventListener("click",func)
  • addEventListenerattachEvent的区别
  1. 触发的顺序不同,addEventListener是从上到下,attachEvent从下到上
  2. addEventListener可以选择是否使用捕获
  3. 兼容性不同,addEvntListener是标准的绑定事件监听函数方法,但在IE8.0及其以下版本不支持,需使用attachEvent。所以使用这种绑定事件的方法需要处理浏览器兼容问题。

处理方法如下:

function addEvent(obj,type,handle){
     
  try{
      // Chrome、FireFox、Opera、Safari、IE9.0及其以上版本
    obj.addEventListener(type,handle,false);
  }catch(e){
     
    try{
      // IE8.0及其以下版本
      obj.attachEvent('on' + type,handle);
    }catch(e){
      // 早期浏览器
      obj['on' + type] = handle;
    }
 }
}
  • 优点:
    (1)同一个节点可以绑定多个同类型事件;
    (2)可以使用removeEventListenerdetachevent取消事件绑定

  • 事件的捕获与冒泡(js中的事件流模型)

四、js中事件流模型

事件:与浏览器或文档交互的瞬间,比如点击按钮、填写表格等,是HTML与JS之间交互的桥梁。

事件流:DOM是树形结构,同时给父节点和子节点绑定事件,当触发子节点的时候,这两个事件的发生顺序就是事件流决定的。描述的是页面中接受事件的顺序。

image

(一)事件冒泡

IE提出的,像水冒泡一样从下往上传播的方式。事件从子节点逐渐向上传播到父节点。

(二)事件捕获

网景公司提出的,与冒泡相反。事件从父节点开始逐渐深入向子节点传播。

(三)DOM事件流

DOM2级事件做了一个比较折中的规范。规定的事件流包含3个阶段:事件捕获阶段、处于目标阶段、事件冒泡阶段

首先发生事件捕获到达实际的目标,实际目标接收事件,最后一个阶段是从实际目标开始冒泡,在这个阶段对事件做出响应。

使用addEventListener进行事件绑定的时候,第三个参数默认为false,设置事件在冒泡阶段进行。

//HTML
<div class="red">
	<div class="green">
		<div class="yellow"></div>
	</div>
</div>

//script
function funa() {
     
  console.log('a')
}
function funb() {
     
  console.log('b')
}
function func() {
     
  console.log('c')
}
document.getElementsByClassName("red")[0].addEventListener("click",funa)
document.getElementsByClassName("green")[0].addEventListener("click",funb)
document.getElementsByClassName("yellow")[0].addEventListener("click",func)

//执行顺序:c->b->a,在冒泡阶段进行事件

当第三个参数为true,设置在捕获阶段执行的时候

document.getElementsByClassName("red")[0].addEventListener("click",funa,true)
document.getElementsByClassName("green")[0].addEventListener("click",funb,true)
document.getElementsByClassName("yellow")[0].addEventListener("click",func,true)

//执行顺序:a->b->c,在捕获阶段进行事件
document.getElementsByClassName("red")[0].addEventListener("click",funa,true)
document.getElementsByClassName("green")[0].addEventListener("click",funb)
document.getElementsByClassName("yellow")[0].addEventListener("click",func,true)

//执行顺序:a->c->b,a和c在捕获阶段进行,b在冒泡阶段进行
  • 什么时候事件冒泡?什么时候事件捕获?
  1. 当使用addEventListener绑定事件,第三个参数传为true时表示事件捕获
  2. 除此之外的所有事件绑定均为事件冒泡
  • 阻止事件冒泡
  1. IE10之前,e.cancelBubble = true;
  2. IE10之后,e.stopPropagation();

如果事件是在捕获阶段进行的,那么阻值冒泡依然会进行

function myParagraphEventHandler(e) {
     
     e = e || window.event;
    if (e.stopPropagation) {
     
         e.stopPropagation(); //IE10以后 
         console.log('stopPropagation')
    } else {
     
         e.cancelBubble = true; //IE10之前
         console.log('cancelBubble')
    }
}
//script
function funa() {
     
  console.log('a')
}
function funb() {
     
  //myParagraphEventHandler()  事件c,b会触发,事件a被截止
  console.log('b')
}
function func() {
     
  //myParagraphEventHandler()  事件c会被触发,事件a,b被冒泡截止
  console.log('c')
}

五、事件委托(事件代理)

前面讲到了事件冒泡,子元素身上的事件会冒泡到父元素身上。而事件代理是:本来加在子元素身上的事件,加在了其父级身上。

  • 父元素的子级比较多,怎么区分事件加在了哪个元素上面?
    使用event对象,在旧的IE版本中事件源是window.event.srcElement,其他浏览器是event.target
  • 事件委托的好处?
    1、效率高,不用使用for循环为子元素一个个添加事件
    2、对于js产生的新的子元素也不用为其添加新的事件了,逻辑上比较方便

使用事件委托之前:

//html
<ul id="ul1">
	<li>111</li>
	<li>222</li>
	<li>333</li>
	<li>444</li>
 </ul>
 
//js
window.onload = function(){
     
	var oUl = document.getElementById('ul1');
	var aLi = oUl.children;
	for (var i=0;i<aLi.length;i++) {
     
		aLi[i].onmouseover = function() {
     
			this.style.background = 'red';
		}
		aLi[i].onmouseout = function(){
     
			this.style.background = '';
		}
	}//for结束
}

使用事件代理:

window.onload = function(){
     
	var oUl = document.getElementById('ul1');
	oUl.onmouseover = function(ev){
     
		var ev = ev || window.event;
		var oLi = ev.srcElement || ev.target;
		if(oLi.nodeName.toLowerCase() == 'li'){
        //判断点击的是不是li元素,防止点击整个ul的时候触发事件
 			Li.style.background = 'red';
		}               
	}
	oUl.onmouseout = function(ev){
     
		var ev = ev || window.event;
		var oLi = ev.srcElement || ev.target;
		if(oLi.nodeName.toLowerCase() == 'li'){
     
			oLi.style.background = '';
 		}                
	}
}
  • event.currentTargetevent.target
    currentTarget:表示此事件绑定的元素,比如绑定的ul
    target:通俗理解为表示触发一系列事件的源头,比如点击的li

六、JS中的事件

(一)鼠标事件

js事件与事件绑定_第1张图片

(二)键盘事件

js事件与事件绑定_第2张图片

(三)对象事件

js事件与事件绑定_第3张图片

(四)表单事件

js事件与事件绑定_第4张图片

(五)拖动事件

(六)多媒体事件

(七)动画事件

(八)过度事件

你可能感兴趣的:(前端,javascript)