JavaScript笔记:事件

event

  • 定义:
  • 事件处理程序
    • 1. HTML事件处理程序
    • 2. elem.onXXX = function(event){}
    • 3. obj.addEventListener(type, fn, false)
    • 4. obj.attachEvent('on' + type, fn);
  • 事件流
    • 事件处理模型
      • 1. 事件冒泡
      • 2. 事件捕获
  • 阻止默认事件
  • 跨浏览器的事件处理程序
  • 事件委托机制
  • 事件对象
    • 键盘事件

定义:

JavaScript与HTML之间的交互是通过事件来实现的。是交互体验的核心功能。

响应事件的函数叫做事件处理程序或事件侦听器。

事件处理程序

1. HTML事件处理程序

<input type="button" value="click me" onclick="alert('clicked')"/>
<input type="button" value="click me" onclick="showMessage()"/>
<input type="button" value="click me" onclick="try{showMessage();}catch(ex){}"/>
<script>
	function showMessage(){alert('hello");}
script>

多数HTML事件被封装在try-catch块中,避免错误出现。例如,假如showMessage()在按钮下方、页面最底部被定义,如果用户在页面解析函数之前单击了按钮,就会引发错误。

2. elem.onXXX = function(event){}

DOM0级事件处理程序

兼容性好,具有跨浏览器的优势,但一个元素的同一事件只能绑定一个处理程序,否则会被覆盖;
程序this指向DOM元素本身
删除事件处理程序: elem.onXXX = null;

<div style="width:100px;height: 100px;background-color: green;"></div>
<script type="text/javascript">
	var div = document.getElementsByTagName('div')[0];
	div.onclick = function(){
		this.style.backgroundColor = 'red';
		//this.onclick = null;解除事件
	}
</script>

3. obj.addEventListener(type, fn, false)

DOM2级事件处理程序

false:在冒泡阶段调用事件处理函数
true:在捕获阶段调用事件处理函数

IE9以下不兼容,可为一个事件绑定多个处理函程序
fn: 函数引用,不是函数声明

程序this指向DOM元素本身

删除事件处理函数:removeEventListner(type, fn, false)
传入参数和添加时相同,意味着添加的匿名函数将无法移除

div.addEventListener('click',function(){
	console.log('a');
}, false)
div.addEventListener('click', test, false);
function test(){console.log('a')}
div.removeEventListener('click', test, false);//解除事件处理函数

在大多数情况下,都是将事件处理程序添加到事件流的冒泡阶段,这样可以最大限度地兼容各种浏览器。

4. obj.attachEvent(‘on’ + type, fn);

IE事件处理程序

IE独有,一个事件可绑定多个处理程序。在全局作用域中运行。
由于IE9以下版本只支持事件冒泡,所以通过attachEvent()添加的事件处理程序都会被添加到冒泡阶段

div.attachEvent('onclick', function(){});
div.detachEvent('onclick', function(){});//删除事件处理程序

事件流

事件捕获阶段->目标阶段->事件冒泡阶段
描述从页面中接收事件的顺序。

事件处理模型

一个对象的一个事件模型只能遵循冒泡或者捕获其中一个模型。
触发顺序:先捕获,后冒泡。
对于非target节点则先执行捕获再执行冒泡
对于target节点则是先执行先注册的事件,无论冒泡还是捕获

1. 事件冒泡

结构上(非视觉上)嵌套关系的元素,会存在事件冒泡的功能,即同一事件,自子元素冒泡向父元素(字底向上)。
传递的是事件,不是所绑定的事件函数,如果父级元素没有绑定事件函数,不会有所表现。
focus, blur, change, submit, reset, select等事件不冒泡。

IE9,Firefox,Chrome,Safari将事件一直冒泡到window。

取消冒泡

  • W3C标准 event.stopPropagation(); 但不支持IE9以下版本
  • IE独有 event.cancelBubble = true;
  • 封装取消冒泡的函数 stopBubble(event)
div.onclick = function(e){
	e.stopPropagation();
	event.cancelBubble = true;
	stopBulle(e);
	this.style.background = 'green';
}
function stopBubble(event){
	if(event.stopPropagation){
		event.stopPropagation();
	}else{
		event.cancelBubble = true;
	}
}

2. 事件捕获

结构上(非视觉上)嵌套关系的元素,会存在事件捕获的功能,即同一事件,自父元素捕获至子元素(事件源元素)。(自顶向下)
IE没有捕获事件

阻止默认事件

  • return false
    以对象属性的方式注册的事件才生效
document.oncontextmenu = function(){
	return false;
}
  • event.preventDefault()
    W3C标准,IE9以下不兼容
  • event.returnValue = false;
    兼容IE
  • 封装阻止默认事件的函数 cancelHandler(event);
function cancelHandler(event){
	if(event.preventDefault){
		event.preventDefault();
	}else{
		event.returnValue = false;
	}
}

跨浏览器的事件处理程序

要保证处理时间的代码能在大多数浏览器下一致地运行,只需关注冒泡阶段。

<input type="button" value="click">
var btn = document.getElementsByTagName('input')[0];
var EventUtil = {
	addHandler: function(elem, type, handler){
		if(elem.addEventListener){
			elem.addEventListener(type, handler, false);
		}else if(elem.attachEvent){
			elem.attachEvent("on" + type, handler);
		}else{
			elem["on" + type] = handler;
		}
	},
	removeHandler: function(elem, type, handler){
		if(elem.removeEventLisetner){
			elem.removeEventListener(type, handler, false);
		}else if(elem.detachEvent){
			elem.detachEvent("on" + type, handler);
		}else{
			elem["on" + type] = null;
		}
	},
	getEvent: function(event){
		return event? event : window.event;
	},
	getTarget: function(event){
		return event.target || srcElement;
	},
	preventDefault: function(event){
		if(event.preventDefault){
			event.preventDefult();
		}else{
			event.returnValue = false;
		}
	},
	stopPropagation: function(event){
		if(event.stopPropagation){
			event.stopPropagation();
		}else{
			event.cancelBubble = true;
		}
	}
};
var handler = function(){document.write('hahahaha')};
EventUtil.addHandler(btn, "click", handler);

事件委托机制

利用事件冒泡和事件源对象进行处理

优点

  • 性能:不需要循环所有的元素逐个绑定事件
  • 灵活:当有新的子元素时,不需要重新绑定事件
<ul>
	<li>1li>
	<li>2li>
	<li>3li>
	<li>4li>
	<li>5li>
ul>
<script type="text/javascript">
	var ul = document.getElementsByTagName('ul')[0];
	ul.onclick = function(e){
		var event = e || window.event;
		var target = event.srcElement || event.target;
		console.log(target.innerText);
	}
script>

事件对象

  • event || window.event 用于IE
  • 事件源对象
    event.target 火狐只有这个
    event.srcElement IE只有这个
    Chrome两者都有

DOM3标准规定:click事件只能监听左键。只能通过mousedown和mouseup来判断鼠标键。

键盘事件

keydown > keypress > keyup

keydown和keypress的区别:

  • keydown可以响应任何键盘按键,keypress只可响应字符类键盘按键
  • keypress返回ASCII码,可以转换成相应字符
document.onkeypress = function(e){
	console.log(String.fromCharCode(e.charCode));
}

实现鼠标拖拽功能

var div = document.getElementsByTagName('div')[0];
function drag(elem){
	var disX, disY;
	elem.onmousedown = function(e){
		var event = e || window.event;
		disY = event.pageY - parseInt(elem.style.top);
		disX = event.pageX - parseInt(elem.style.left);
		document.onmousemove = function(e){
			var event = e || window.event;
			elem.style.top = event.pageY - disY + "px";
			elem.style.left = event.pageX - disX + "px";
		}
		document.onmouseup = function(){
			document.onmousemove = null;
		}
	}
}
drag(div);
//封装
function drag(elem){
	var disX,
		disY;
	addEvent(elem, 'mousedown', function(e){
		var event = e || window.event;
		disX = event.clientX - parseInt(getStyle(elem, 'left'));
		disY = event.clientY - parseInt(getStyle(elem, 'top'));
		addEvent(document, 'mousemove', mouseMove);
		addEvent(document, 'mouseup', mouseUp);
		stopBubble(event);
		cancelHandler(event);
	});
	function mouseMove(e){
		var event = e || window.event;
		elem.style.left = event.clienX - disX + "px";
		elem.style.top = event.clientY - disY + "px";
	}
	function mouseUp(e){
		var event = e || window.event;
		removeEvent(document, 'mousemove', mouseMove);
		removeEvent(document, 'mouseup', mouseUp);
	}
}

你可能感兴趣的:(前段)