JavaScript与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()在按钮下方、页面最底部被定义,如果用户在页面解析函数之前单击了按钮,就会引发错误。
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>
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);//解除事件处理函数
在大多数情况下,都是将事件处理程序添加到事件流的冒泡阶段,这样可以最大限度地兼容各种浏览器。
IE事件处理程序
IE独有,一个事件可绑定多个处理程序。在全局作用域中运行。
由于IE9以下版本只支持事件冒泡,所以通过attachEvent()添加的事件处理程序都会被添加到冒泡阶段
div.attachEvent('onclick', function(){});
div.detachEvent('onclick', function(){});//删除事件处理程序
事件捕获阶段->目标阶段->事件冒泡阶段
描述从页面中接收事件的顺序。
一个对象的一个事件模型只能遵循冒泡或者捕获其中一个模型。
触发顺序:先捕获,后冒泡。
对于非target节点则先执行捕获再执行冒泡
对于target节点则是先执行先注册的事件,无论冒泡还是捕获
结构上(非视觉上)嵌套关系的元素,会存在事件冒泡的功能,即同一事件,自子元素冒泡向父元素(字底向上)。
传递的是事件,不是所绑定的事件函数,如果父级元素没有绑定事件函数,不会有所表现。
focus, blur, change, submit, reset, select等事件不冒泡。
IE9,Firefox,Chrome,Safari将事件一直冒泡到window。
取消冒泡
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;
}
}
结构上(非视觉上)嵌套关系的元素,会存在事件捕获的功能,即同一事件,自父元素捕获至子元素(事件源元素)。(自顶向下)
IE没有捕获事件
document.oncontextmenu = function(){
return false;
}
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>
DOM3标准规定:click事件只能监听左键。只能通过mousedown和mouseup来判断鼠标键。
keydown > keypress > keyup
keydown和keypress的区别:
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);
}
}