绑定事件处理函数
ele.onxxx = function(event){}
- 兼容性很好,但是一个元素的同一个事件只能绑定一个处理程序
- 基本等同于写在HTML行间上,绑定在HTML行间上的事件被称为句柄事件
- 程序this指向是dom元素本身
obj.addEventListener(type, fn, false);
- IE9以下不兼容,可以为一个事件绑定多个处理程序
- 程序this指向是dom元素本身
obj.attachEvent('on'+type, fn);
- IE独有,一个事件同样可以绑定多个处理程序
- 程序this指向是window
解除事件处理程序
ele.onclick = false/null/'';
ele.removeEventListener(type,fn,false);
ele.detachEvent('on'+type,fn);
- 若绑定匿名函数,则无法解除
给每个li元素绑定一个click事件
// 1. 给每个li绑定事件
var liCol = document.getElementsByTagName('li'),
len = liCol.length;
for (var i = 0; i < len; i++) {
(function (i) {
liCol[i].addEventListener('click', function () {
console.log(i);
}, false)
}(i))
}
// 2. 每li的父元素绑定事件,进行事件代理
var ulCol = document.getElementsByTagName('ul')[0];
ulCol.addEventListener('click',function(e){
e = e || window.event;
var target = e.target || e.srcElement;
console.log(target);
},false);
封装兼容性方法,事件处理函数 addEvent(elem,type,handle)
function addEvent(elem, type, handle) {
if (elem.addEventListener) {
elem.addEventListener(type, handle, false);
} else if (elem.attachEvent) {
elem.attachEvent('on' + type, function () {
handle.call(elem);
})
} else {
elem['on' + type] = handle;
}
}
事件处理模型-事件冒泡、捕获
- 事件冒泡
目标元素 => ...(dom节点) => body => html => document => window
- 结构上(非视觉)嵌套关系的元素,会存在事件冒泡的功能,即同一事件,自子元素冒泡向父元素。(自底向上)
- 事件捕获
window => document => html => body => ...(dom节点) => 目标元素
- 结构上(非视觉)嵌套关系的元素,会存在事件捕获的功能,即同一事件,自父元素捕获至子元素(事件源元素)。(自顶向下)
- IE没有捕获事件
- 触发顺序,先捕获,后冒泡
focus blur change submit reset select 等事件不冒泡
取消冒泡,阻止默认事件
- 取消冒泡
- W3C标准
event.stopPropagation(); 不支持IE9以下版本
- IE独有
event.cancelBubble = true;
- 封装取消冒泡的函数
stopBubble(event);
function stopBubble(event) {
event = event || window.event;
if (event.stopPropagation) {
event.stopPropagation();
} else {
event.cancelBubble = true;
}
}
- 阻止默认事件
- 默认事件-表单提交,a标签跳转,右键菜单等
-
return false; 以对象属性的方式注册的事件才生效
-
event.preventDefault(); W3C标注,IE9以下不兼容
-
event.returnValue = false; 兼容IE
- 封装阻止默认事件的函数
cancelHandler(event);
function cancelHandler(event) {
event = event || window.event;
if (event.preventDefault) {
event.preventDefault();
} else {
event.returnValue = false;
}
return false;
}
事件对象
event || window.event 用于IE
- 事件源对象:
- event.target 火狐只有这个
- event.srcElement IE只有这个
- 这俩chrome都有
- 兼容性写法
var ul = document.getElementsByTagName('ul')[0];
ul.onclick = function(e){
var event = e || window.event;
var target = event.target || event.srcElement;
console.log(target.innerText);
}
事件分类
- 鼠标事件 :
click mousedown mousemove mouseup contextmenu mouseover mouseout mouseenter mouseleave
- 用button来区分鼠标的按键,0左/1中/2右
- DOM3标准规定:click事件只能监听左键,只能通过
mousedown 和 mouseup 来判断鼠标键
- 解决
mousedown 和 click 冲突,使用锁key+300ms
// 300ms以内为点击事件,300ms以外为拖拽事件
var firstTime = 0;
var lastTime = 0;
var key = false;
document.onmousedown = function () {
firstTime = new Date().getTime();
}
document.onmouseup = function () {
lastTime = new Date().getTime();
if (lastTime - firstTime < 300) {
key = true;
}
}
document.onclick = function () {
if (key) {
console.log('click');
key = false;
}
}
拖拽函数
function drag(elem) {
var disX,
disY;
elem.onmousedown = function (e) {
disX = e.pageX - parseInt(elem.style.left);
disY = e.pageY - parseInt(elem.style.top);
document.onmousemove = function (e) {
var event = e || window.event;
elem.style.left = e.pageX - disX + 'px';
elem.style.top = e.pageY - disY + 'px';
}
document.onmouseup = function () {
document.onmousemove = null;
}
}
}
拖拽函数优化
function stopBubble(event) {
event = event || window.event;
if (event.stopPropagation) {
event.stopPropagation();
} else {
event.cancelBubble = true;
}
}
function cancelHandler(event) {
event = event || window.event;
if (event.preventDefault) {
event.preventDefault();
} else {
event.returnValue = false;
}
return false;
}
function getStyle(elem, prop) {
if (window.getComputedStyle) {
return window.getComputedStyle(elem, null)[prop]
} else {
return elem.currentStyle[prop];
}
}
function addEvent(elem, type, handle) {
if (elem.addEventListener) {
elem.addEventListener(type, handle, false);
} else if (elem.attachEvent) {
elem.attachEvent('on' + type, function () {
handle.call(elem);
})
} else {
elem['on' + type] = handle;
}
}
function removeEvent(elem, type, handle) {
if (elem.removeEventListener) {
elem.removeEventListener(type, handle, false);
} else if (elem.detachEvent) {
elem.detachEvent('on' + type, function () {
handle.call(elem);
})
} else {
elem['on' + type] = null;
}
}
function drag(elem) {
var disX,
disY;
addEvent(elem, 'mousedown', function (e) {
var event = e || window.event;
disX = event.pageX - parseInt(getStyle(elem, 'left'));
disY = event.pageY - 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.clientX - disX + "px";
elem.style.top = event.clientY - disY + "px";
}
function mouseUp(e) {
var event = e || window.event;
removeEvent(document, 'mousemove', mouseMove);
}
}
键盘事件
keydown keyup keypress
keydown > keypress > keyup
keydown 和 keypress的区别
- keydown 可以响应任意键盘按键,keypress只可能响应字符类键盘按键
- keypress 返回ASCII码,可以转换成相应字符
String.fromCharCode(e.charCode)
input事件
<input type="text" value="请输入用户名" style="color: #999;" onfocus="if(this.value=='请输入用户名'){this.value = '';this.style.color='#424242'}" onblur="if(this.value==''){this.value = '请输入用户名';this.style.color='#999'}" />
- oninput onchange