(十三)JavaScript 事件详解

绑定事件的监听函数 (事件处理函数)

(1)HTML 的 on- 属性
<body onload="doSomething()">
<div onclick="console.log('触发事件')">

元素的事件监听属性,都是on加上事件名,比如click就是on + click,表示click事件的监听代码。
注意,这些属性的值是将会执行的代码,而不是一个函数。

(2)元素节点的事件属性
function doSomething(){
	console.log('页面加载完毕');
}
window.onload = doSomething;
// <div class="myDiv" >mydiv</div>
var div = document.getElementsByClassName('myDiv')[0];
div.onclick = function(){
	console.log('触发点击事件');
}

元素节点的事件属性,也都是on加上事件名,比如click就是on + click,表示click事件的监听函数。
不同的是,它的值是函数名
同一个事件只能绑定一个监听函数,也就是说,如果定义两次onclick属性,后一次定义会覆盖前一次

解除绑定,可以 div.onclick = null
如:

// <div class="myDiv" >mydiv</div>
var div = document.getElementsByClassName('myDiv')[0];
div.onclick = function(){
	console.log('触发点击事件');
	this.onclick = null; // 点击一次后就被取消
}
(3)addEventListener()
function doSomething(){
	console.log('页面加载完毕');
}
window.addEventListener('load', doSomething, false);
// <div class="myDiv" >mydiv</div>
var div = document.getElementsByClassName('myDiv')[0];
div.addEventListener('click',function(){
	console.log('触发点击事件');
},false);

一个对象的同一个事件可以添加多个监听函数
addEventListener()兼容性:IE 9 以下的IE浏览器不兼容

addEventListener() 的三个参数分别为

  1. 事件名称
  2. 监听函数
  3. 布尔值,true 表示监听函数在捕获阶段触发,false 表示监听函数在冒泡阶段触发,默认为false。该参数可选。

解除绑定,removeEventListener(type, fn, false);
解绑时,事件和监听函数要对应。如果绑定匿名函数,则无法解除绑定。

(4)attachEvent()

IE独有的函数
attachEvent( 'on'+ 事件名称 , 监听函数 )

// <div class="myDiv" >mydiv</div>
var div = document.getElementsByClassName('myDiv')[0];
div.attachEvent('onclick', function(){
	console.log('触发点击事件');
})

一个对象的同一个事件可以添加多个监听函数

解除绑定,detachEvent('on' + type, fn);
解绑时,事件和监听函数要对应。如果绑定匿名函数,则无法解除绑定。

this 的指向

以上四个 绑定事件的监听函数的方法中,
除了attachEvent()中的监听函数内部的this指向window
其余三个,监听函数内部的this指向触发事件的那个元素节点本身。


封装一个有兼容性的,绑定事件的监听函数的方法

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);  //为了 handle 函数里面的 this 指向触发事件的那个元素节点本身
		});
	}else{
		elem['on' + type] = handle;
	}
}

关于绑定事件处理函数出现的闭包
一但绑定事件的处理函数出现在了循环里面,就要注意是否形成闭包。

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Document</title>
</head>
<body>
<ul>
	<li>1</li>
	<li>2</li>
	<li>3</li>
	<li>4</li>
</ul>
<script type="text/javascript">
    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);
	    		//console.log(this.innerHTML);
	    	})
    	}(i))
    }
</script>
</body>
</html>

事件对象

事件发生以后,会产生一个事件对象,作为参数传给监听函数。(IE不会把事件对象传到监听函数里面,会传到window.event
事件对象里包含了当前事件发生时的状态和信息。

事件对象的一些属性
事件源对象:

event.target 火狐使用这个表示
event.srcElement IE 使用这个表示
chrome浏览器两者都有

//<div class="myDiv" ><p>点击</p></div>
var div = document.getElementsByTagName('div')[0];
var p = document.getElementsByTagName('p')[0];
div.onclick = function(e){
	var event = e || window.event; // 兼容性写法,
	//或 || 从左到右执行判断两边的表达式,如左边表达式为ture,则直接返回左边表达式的值,不再执行右边表达式进行判断;
	console.log(event);
	var target = event.target || event.srcElement; // 兼容性写法,
	console.log(target); // <p>点击</p>
}

事件的传递

一个事件发生后,会在子元素和父元素之间传播。
触发顺序:先捕获,后冒泡
IE没有捕获阶段

捕获阶段:从window对象传导到目标节点(从父元素传递到子元素)
冒泡阶段:从目标节点传导回window对象(从子元素传递到父元素)
focus,blur,change,submit,reset,select等事件不冒泡。

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Document</title>
</head>
<body>
<div>
  <p>点击</p>
</div>
<script>
var div = document.getElementsByTagName('div')[0],
	p   = document.getElementsByTagName('p')[0];
function test(){
	console.log(this.tagName);
}

div.addEventListener('click', test, true);
p.addEventListener('click', test, true);
div.addEventListener('click', test, false);
p.addEventListener('click', test, false);
</script>
</body>
</html>
// DIV P P DIV

上例,<p>点击</p> 被点击。事件传播顺序,在捕获阶段依次为window、document、html、body、div、p,在冒泡阶段依次为p、div、body、html、document、window

取消冒泡
(1)W3C标准 event.stopPropagation(); (兼容性:IE9 以下版本不支持)
(2)IE 可使用 event.cancelBubble = true;
如:

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Document</title>
</head>
<body>
<div>
  <p>点击</p>
</div>
<script>
var div = document.getElementsByTagName('div')[0],
	p   = document.getElementsByTagName('p')[0];
function test(event){
	event.stopPropagation(); // 取消冒泡
	//event.cancelBubble = true;
	console.log(this.tagName);
}
div.onclick = test;
p.onclick = test;
</script>
</body>
</html>
// p

封装取消冒泡函数

function stopBubble(event){
	if(event.stopPropagation){
		event.stopPropagation();
	}else{
		event.cancelBubble = true;
	}
}

阻止默认事件

默认事件,如表单提交,a标签跳转,右键菜单等
(1)return false; (绑定事件的监听函数 使用第(1)、(2)种方法时,才有效。)
(2)W3C标准 event.preventDefault(); (兼容性:IE9 以下版本不支持)
(3)IE 可使用 event.returnValue = false;

封装阻止默认事件函数

function cancelHandler(event){
	if (event.preventDefault) {
		event.preventDefault();
	}else{
		event.returnValue = false;
	}
}

<a> 标签拿来当按钮用时,取消<a> 标签的默认事件,还可以在href中使用协议限定符javascript:

<a href="" onclick="doSomething();return false">baidu.com</a>
<!-- 或 --> 
<a href="javascript:void(0)" onclick="doSomething()">baidu.com</a>

事件的代理(委托)

利用了事件冒泡事件源对象进行处理。
由于事件会在冒泡阶段向上传播到父节点,因此可以把子节点的监听函数定义在父节点上,由父节点的监听函数统一处理多个子元素的事件。这种方法叫做事件的代理(delegation)。

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Document</title>
</head>
<body>
<ul>
	<li>1</li>
	<li>2</li>
	<li>3</li>
	<li>4</li>
</ul>
<script>
var ul = document.getElementsByTagName('ul')[0];
ul.onclick = function(e){
	var event = e || window.event; // 兼容性写法
	var target = event.target || event.srcElement; // 兼容性写法
	console.log(target.innerHTML); 
}
</script>
</body>
</html>

鼠标事件

mousedown:按下鼠标键时触发。
mouseup:释放按下的鼠标键时触发。
click:点击鼠标时触发。指的是,用户在同一个位置先完成mousedown动作,再完成mouseup动作。
因此,触发顺序是,mousedown首先触发,mouseup接着触发,click最后触发。
mousemove:当鼠标在一个节点内部移动时触发。

mouseenter:鼠标进入一个节点时触发。
mouseleave:鼠标离开一个节点时触发。

mouseover:鼠标进入一个节点时触发。
mouseout:鼠标离开一个节点时触发。

mouseover事件和mouseenter事件,都是鼠标进入一个节点时触发。两者的区别是,mouseenter事件只触发一次,而只要鼠标在节点内部移动,mouseover事件会在子节点上触发多次。
mouseout事件和mouseleave事件,都是鼠标离开一个节点时触发。两者的区别是,在父元素内部离开一个子元素时,mouseleave事件不会触发,而mouseout事件会触发。

contextmenu:按下鼠标右键时(上下文菜单出现前)触发。

鼠标事件对象的event.button属性来区分鼠标的按键,0表示左键,1表示中间,2表示右键。
DOM3标准规定:click 事件只能监听鼠标左键,只能通过mousedown和mouseup来判断鼠标键

拖拽的例子:

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Document</title>
</head>
<body>
<div style="width: 100px; height: 100px; background-color: red; position: absolute; left:0;top: 0;"></div>
<script>
var div = document.getElementsByTagName('div')[0];

function drag(elem){
	elem.onmousedown = function(e){
		var event = e || window.event;
		// console.log(' 点 ');
		var disX = event.offsetX,
			disY = event.offsetY;
		document.onmousemove = function(e){
			var event = e || window.event;
			div.style.left = e.pageX - disX + 'px';
			div.style.top = e.pageY - disY + 'px';
		}
		elem.onmouseup = function(){
			// console.log(' 松 ');
			document.onmousemove = null;
		}
	}
}
drag(div);
</script>
</body>
</html>

键盘事件

(略)

文本操作事件

input 事件
<input><select><textarea>的值发生变化时触发。对于复选框(<input type=checkbox>)或单选框(<input type=radio>),用户改变选项时,也会触发这个事件。

var input = document.getElementsByTagName('input')[0];
input.oninput = function(){
	console.log(this.value);
}

change事件
change在元素失去焦点时发生,如果值发生了变化,则触发。
focus事件,元素获得焦点
blur事件,元素失去焦点

// <input type="text" value="请输入关键字" style="color: #999;">
var input = document.getElementsByTagName('input')[0];
input.onfocus = function(){
	if (this.value == '请输入关键字') {this.value = '';}
	this.style.color = '#424242';
}
input.onblur = function(){
	if(this.value == ''){this.value = '请输入关键字';}
	this.style.color = '#999';
}

窗体操作类事件(window上的事件)

scroll事件,当滚动条滚动时触发。

load事件,在页面或某个资源加载成功时触发。
window.onload = function(){ } 整个页面资源加载完后触发。一般不用

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值