js基础十七-- 事件对象、事件委托、事件分类
一、事件对象
event || window.event
事件源对象:
event.target 火狐、谷歌
event.srcElement Ie、谷歌
target和srcElement是事件对象event身上的两个属性,记录着事件触发的源头(事件源对象)

例如:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>文档标题</title>
<style type="text/css">
.wrapper {
width: 200px;
height: 200px;
background-color: red;
}
.content {
width: 100px;
height: 100px;
background-color: black;
}
.box {
width: 50px;
height: 50px;
background-color: #ccc;
}
</style>
</head>
<body>
<div class="wrapper">
<div class="content">
<div class="box"></div>
</div>
</div>
<script type="text/javascript">
var wrapper = document.getElementsByClassName("wrapper")[0];
var content = wrapper.children[0];
var box = content.children[0];
box.onclick = function(e) {
console.log(e.target); // 打印事件源对象
console.log("a");
e.stopPropagation(); // 阻止事件冒泡
}
content.onclick = function(e) {
console.log(e.target); // 打印事件源对象
console.log("b");
e.stopPropagation(); // 阻止事件冒泡
}
wrapper.onclick = function(e) {
console.log(e.target); // 打印事件源对象
console.log("c");
}
</script>
</body>
</html>
点击box,打印后的事件源对象为:

点击content,打印后的事件源对象为:

点击wrapper,打印后的事件源对象为:

二、事件委托
// 利用事件冒泡,和事件源对象进行处理 //【优点】: // 1、提高性能,不需要循环所有的元素一个个绑定事件 // 2、灵活当有新的子元素时,不需要重新绑定事件
先来看一个简单案例
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>文档标题</title>
</head>
<body>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
<li>7</li>
<li>8</li>
<li>9</li>
<li>10</li>
</ul>
<script type="text/javascript">
// 事件委托
// 要求,给每个li注册点击事件并输出每个li的内容
var ul = document.getElementsByTagName("ul")[0];
ul.onclick = function(e) {
var event = e || window.event; // 兼容IE
var target = e.target || e.srcElement; // 获取事件源对象
console.log(target.innerText); // 打印出事件源对象的文本内容
}
</script>
</body>
</html>
通过获取父级,将事件委托(冒泡)给父级对象,并通过获取事件源对象的文本内容,来得到相应结果。减少多余的循环操作,提高性能、优化代码。
控制台打印结果如下:

三、事件分类
鼠标事件
// 【鼠标事件】 // click(点击)、mousedown(按下)、mousemove(移动)、mouseup(抬起)、mouseover(鼠标进入)、mouseout(鼠标移出)、mouseenter(鼠标进入h5)、mouseleave(鼠标移出h5)、contextmenu(右键菜单)
事件对象中有一个属性button用来区分鼠标的按键 0(左)/1(中)/2(右)
注意:DOM3标准规定:click事件只能监听左键,只能通过mousedown或者mouseup来判断鼠标键
如何解决mousedown和click冲突? 我们可以利用时间戳来判断是点击还是拖拽。
var firstTime, lantTime, key = false; document.onmousedown = function(e) { firstTime = new Date().getTime(); // 鼠标按下时获取最新时间
// document.onmousemove... } document.onmouseup = function(e) { lantTime = new Date().getTime(); // 鼠标抬起时再次获取最新时间 if (lantTime - firstTime < 300) { // 如果鼠标抬起时间小于300,则判断为点击事件,执行点击事件里的事件处理程序,如果大于或等于300则执行拖拽事件 key = true; } } document.onclick = function(e) { if (key) { console.log("点击事件"); key = false; } }
键盘类事件
// 【键盘事件】 // keydown(键盘按下)、keyup(键盘抬起)、keypress (键盘按下)
来看一下上面三个事件在控制台的反应速度:
// keydown > keypress > keyup
document.onkeypress = function(e) { console.log("onkeypress"); } document.onkeydown = function(e) { console.log("onkeydown"); } document.onkeyup = function(e) { console.log("onkeyup"); }
按下任意键,控制台反应结果:

//【keydown和keypress区别】 // keydown可以响应任意键盘按键,keypress只可以响应字符类键盘按键,keypress可以返回asscll码,可以转换成相应字符
打印两个事件的事件对象:
document.onkeypress = function(e) { console.log(e); } document.onkeydown = function(e) { console.log(e); }
按下键盘上字母k后,控制台事件对象的返回结果为:

因此直接打印两个事件返回的asscll码:
document.onkeypress = function(e) { console.log(e.charCode); } document.onkeydown = function(e) { console.log(e.charCode); }
控制台返回结果为:

因此,当我们得到返回的asscll码后,可以通过字符串方法String.fromCharCode();将asscll码转换成对应的按键名
document.onkeypress = function(e) { console.log(String.fromCharCode(e.charCode)); }
控制台输入对应按键以及按shift输入对应键,打印结果如下:

文本操作事件
// 【文本操作事件】 // input(文本变化监听)、change(失去焦点并且状态发生改变时触发)
// focus(获得焦点时触发) 、blur(失去焦点时触发)
来看实际例子:
<input type="text">
<script type="text/javascript">
var input = document.getElementsByTagName("input")[0];
input.oninput = function(e) {
console.log(this.value);
}
input.onchange = function(e) {
console.log(this.value);
}
</script>
查看控制台监听结果:

// 【提示】:onfocus 事件的相反事件为 onblur 事件
<input type="text" value="请输入用户名" onfocus="if(this.value=='请输入用户名'){this.value = '';this.style.color = '#424242';}" onblur="if(this.value == ''){this.value = '请输入用户名';this.style.color='#999'}" >
窗体操作类事件
窗体操作类(window)事件:scroll、load【重要】--不建议用、效率低
移动端事件汇总
移动端事件:touchstart、touchmove、touchend 1. click事件 单击事件,类似于PC端的click,但在移动端中,连续click的触发有200ms ~ 300ms的延迟 2. touch类事件 触摸事件,有touchstart touchmove touchend touchcancel 四种之分 touchstart:手指触摸到屏幕会触发 touchmove:当手指在屏幕上移动时,会触发 touchend:当手指离开屏幕时,会触发 touchcancel:可由系统进行的触发,比如手指触摸屏幕的时候,突然alert了一下,或者系统中其他打断了touch的行为,则可以触发该事件 3. tap类事件 触碰事件,我目前还不知道它和touch的区别,一般用于代替click事件,有tap longTap singleTap doubleTap四种之分 tap: 手指碰一下屏幕会触发 longTap: 手指长按屏幕会触发 singleTap: 手指碰一下屏幕会触发 doubleTap: 手指双击屏幕会触发 4. swipe类事件 滑动事件,有swipe swipeLeft swipeRight swipeUp swipeDown 五种之分 swipe:手指在屏幕上滑动时会触发 swipeLeft:手指在屏幕上向左滑动时会触发 swipeRight:手指在屏幕上向右滑动时会触发 swipeUp:手指在屏幕上向上滑动时会触发 swipeDown:手指在屏幕上向下滑动时会触发
案例:封装拖拽函数drag(elem);
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>文档标题</title>
<style type="text/css">
.box {
width: 100px;
height: 100px;
background-color: red;
position: absolute;
left: 0;
top: 0;
}
.content {
width: 200px;
height: 200px;
background-color: blue;
position: absolute;
left: 0;
top: 0;
}
</style>
</head>
<body>
<div class="content"></div>
<div class="box"></div>
<!-- 引入外部工具js -->
<script src="js/Tools.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
// 获取DOM
var content = document.getElementsByClassName("content")[0];
var box = document.getElementsByClassName("box")[0];
// 封装拖拽函数
function drag(elem) {
// 1、获取浏览器可见区域宽高,元素宽高
var browserWidth = document.documentElement.clientWidth,
browserHeight = document.documentElement.clientHeight,
elemWidth = elem.offsetWidth,
elemHeight = elem.offsetHeight;
// 3.1 移动事件处理程序
function mouseMove(e) {
var event = e || window.event; // // 兼容IE
var target = e.target || e.srcElement;
// 目标元素距离左侧距离 = 移动中鼠标点距离文档左侧的距离 - 鼠标相对于目标元素左侧距离
elem.style.left = (e.clientX - disX) + "px";
// 判断目标元素是否移出浏览器可视区域
if ((e.clientX - disX) <= 0) {
elem.style.left = 0;
} else if ((elemWidth - disX + e.clientX) >= browserWidth) {
elem.style.left = browserWidth - elemWidth + "px";
}
// 目标元素距离顶部距离 = 移动中鼠标点距离文档顶部的距离 - 鼠标相对于目标元素顶部距离
elem.style.top = (e.clientY - disY) + "px";
// 判断目标元素是否移出浏览器可视区域
if ((e.clientY - disY) <= 0) {
elem.style.top = 0;
} else if ((elemHeight - disY + e.clientY) >= browserHeight) {
elem.style.top = browserHeight - elemHeight + "px";
}
}
// 3.2 移动事件处理程序
function mouseUp(e) {
var event = e || window.event;
// 4、移除鼠标移动、抬起事件以及相关事件处理程序
removeEvent(document, "mousemove", mouseMove); // 清除鼠标移动事件以及事件处理程序
removeEvent(document, "mouseup", mouseUp); // 清除鼠标抬起事件以及事件处理程序
}
var disX,
disY;
addEvent(elem, "mousedown", function(e) {
var event = e || window.event;
// 2、记录鼠标相对于目标元素左侧以及顶部距离
disX = e.clientX - this.offsetLeft;
disY = e.clientY - this.offsetTop;
// 3、以整个文档为目标,建立鼠标移动、抬起事件并设置相关事件处理程序
addEvent(document, "mousemove", mouseMove); // 添加鼠标移动事件以及事件处理程序
addEvent(document, "mouseup", mouseUp); // 添加鼠标移动事件以及事件处理程序
stopBubble(event); // 阻止冒泡
cancelHandler(event); // 阻止默认事件
});
}
// 调用拖拽函数
drag(box);
drag(content);
</script>
</body>
</html>

浙公网安备 33010602011771号