事件
一.什么是事件?
事件是可以被 JavaScript 侦测到的行为,例如,在用户点击某按钮时产生一个事件,然后去执行某些操作。事件是指 HTML 元素在状态改变、操作鼠标或键盘时触发的动作。包括:状态改变事件、鼠标事件、键盘事件
二.事件三要素
1.事件源:触发事件的元素,即这个事件发生在哪个元素上面
2.事件类型:指具体是什么事件,例如 onclick 点击事件
3.事件处理程序:事件触发后要执行的 js 代码,一般写在函数里面,这个函数叫事件处理函数
例:
<body>
<button type="button">路飞</button>
</body>
<script type="text/javascript">
var btn = document.querySelector('button') //获取事件源
btn.onclick = function(){ //绑定事件,onclick事件
console.log('是要成为海贼王的男人'); //事件处理函数
}
</script>
三.事件的绑定
事件的绑定:即给元素添加事件,又称为绑定事件或注册事件。有以下3种方式
1.行内绑定(以属性的方式写在行内)
同一个元素同一个事件只能设置—个处理函数,最后面的会覆盖掉前面的
<body>
<button type="button" onclick="javascript:first()";>路飞</button>
</body>
<script type="text/javascript">
function first(){
console.log('是要成为海贼王的男人');
}
</script>
2.动态绑定(写在js代码中的)
<body>
<button type="button">路飞</button>
</body>
<script type="text/javascript">
var btn = document.querySelector('button') //获取事件源
btn.onclick = function(){ //绑定事件,onclick事件
console.log('是要成为海贼王的男人'); //事件处理函数
}
</script>
四.事件的监听
1.元素对象.addEventListener('事件名', 匿名函数); //IE9及其以上才支持
2.元素对象.attacheEvent('事件名', 匿名函数); //IE8及其以下才支持
<body>
<button type="button">何海杰</button>
</body>
<script type="text/javascript">
// 传统方法注册事件
var btn = document.querySelector('button')
btn.attachEvent('onclick',function(){
console.log('他是好人');
})
// 只适用于ie8以下的,很少用
</script>
<body>
<button type="button" onclick="javascript:first()">何海杰</button>
<button type="button">杜士博</button>
</body>
<script type="text/javascript">
// 传统方法注册事件
var btn = document.querySelector('button')
btn.onclick = function(){
console.log('是好人');
}
btn.onclick = function(){
console.log('不是人');
}
// 这样只会打印最后面的处理函数
// 监听事件注册
var btn1 = btn.nextElementSibling;
btn1.addEventListener('click',function(){
console.log('是好人');
})
btn1.addEventListener('click',function(){
console.log('老帅了');
})
// 这样只会打印两个处理函数,但ie9以下不兼容
</script>
五.事件的解绑
事件的解绑:即删除在元素上添加的事件,又称为解绑事件或删除事件
1.传统事件的解绑
元素对象.事件名(带on) = null 或 元素对象['事件名(带on)'] =null
<body>
<button type="button">何海杰</button>
</body>
<script type="text/javascript">
// 传统事件的解绑
// 如果不解绑,点击一次就会打印一次
var btn = document.querySelector('button')
btn.onclick = function(){
console.log('是好人');
btn.onclick = null; //加了解绑,只会打印一次
}
</script>
2.监听事件的解绑
1.元素对象.removeEventListener('事件名(不带on)', 函数名); // IE9及其以上才支持
2.元素对象.detacheEvent('事件名(带on)', 函数名); // IE8及其以下才支持
<body>
<button type="button" >何海杰</button>
<button type="button" >杜士博</button>
</body>
<script type="text/javascript">
// 监听事件的解绑
var btn = document.querySelector('button');
// 监听事件的解绑不能用匿名函数
btn.addEventListener('click',fn)
function fn(){
console.log('他很善良,是个好人');
btn.removeEventListener('click',fn) //监听事件解绑,ie9以上支持
}
var btn1 = btn.nextElementSibling;
btn1.addEventListener('onclick',fn)
function fn(){
console.log('他很帅,也是个好人');
btn1.removeEventListener('onclick',fn) //监听事件解绑,ie8以下支持,很少用
}
</script>
六.事件流
1.什么是事件流
html中的标签都是相互嵌套的,我们可以将元素想象成一个盒子装一个盒子,document是最外面的大盒子, 当你单击一个div时,同时你也单击了div的父元素,甚至整个页面, 比如给页面中的一个div注册了单击事件,当你单击了div时,也就单击了body,单击了html,单击了document
事件发生时会在元素节点之间按照特定的顺序传播,这个传播过程,我们称之为事件流
2.事件流的三个阶段
1.事件捕获阶段:事件开始时,由DOM最顶层节点开始,然后逐级向下,一直传播到最具体的元素接收的过程
2.处于目标阶段:事件到达最具体的这个元素时
3.事件冒泡阶段:事件开始时,由最具体的元素接收,然后逐级向上,一直传播到DOM最顶层节点的过程
3.事件流的使用
1.W3C规定事件流遵循先捕获再冒泡的顺序,实际开发中很少使用事件捕获,我们更关注事件冒泡
2.事件冒泡有时候会带来麻烦,有时候又会帮助很巧妙的做某些事件
3.JS代码中只能执行捕获或者冒泡其中的一个阶段
4.有些事件只能得到冒泡阶段,比如:onclick(一般用on开头的都没有捕获阶段)
代码验证:
<style type="text/css">
.father{
width: 300px;
height: 300px;
background-color: red;
}
.son{
width: 150px;
height: 150px;
background-color: green;
margin: 50px auto;
}
</style>
</head>
<body>
<div class="father">大盒子
<div class="son">小盒子</div>
</div>
</body>
<script type="text/javascript">
var son = document.querySelector('.son');
son.onclick = function() {
console.log('您点击了小盒子');
}
var father = document.querySelector('.father');
father.onclick = function() {
console.log('您点击了大盒子');
}
var body = document.body;
body.onclick = function() {
console.log('您点击了body');
}
var html = document.documentElement;
html.onclick = function() {
console.log('您点击了html');
}
document.onclick = function() {
console.log('您点击了document');
}
</script>
// 注:即使调整以上代码的顺序,依然会按照冒泡的顺序执行,而不是按照代码的顺序。
5.有些事件是没有冒泡的,比如:onfocus、onblur、onmouseenter、onmouseleave
6.addEventListener 的第三个参数为 true,则为捕获阶段,为false或者省略,则为冒泡阶段
7.attachEvent 只能得到冒泡阶段
8.(以上没有代码演示)
七.常用事件
事件 | 描述 |
onclick | 用户点击html元素 |
onload | 浏览器已完成页面的加载。即浏览器完成页面的加之后自动触发该事件 |
onchange | HTML 元素改变。比如用户修改了表单的内容之后触发该事件 |
onfocus | 获得鼠标焦点触发 |
onblur | 失去焦点触发 |
onmouseleave | 鼠标离开元素瞬间出发,只触发一次 |
onmouseenter | 鼠标进入元素瞬间出发,只触发一次 |
onmouseout | 鼠标离开元素瞬间触发,可触发多次 |
onmouseover | 鼠标进入元素瞬间触发,可触发多次 |
onkeypress | 用户按下键盘后触发,功能键不会触发 |
onkeydown | 用户按下键盘后触发,所有按键 |
onkeyup | 用户按下键盘后触发,所有按键 |
1.onload案例
<body>
<h1>onload事件演示2</h1>
<script type="text/javascript">
var h1 = document.querySelector('h1')
function first() {
h1.style.color = 'red';
}
document.body.onload = first;
</script>
</body>
2.onchange,onfocus,onblur案例
<body>
<input placeholder="请输入一个字符" onchange="first()"/><br>
<input placeholder="请输入另一个字符" onchange="sec()"/><br>
<input placeholder="请输入另一个字符" onfocus="first()" onblur="sec()"/>
</body>
<script type="text/javascript">
function first(){
var ipt = document.querySelector('input')
ipt.value = ipt.value.toUpperCase() // 第一个input框内输入的字母变为大写
/* ipt.value = ipt.value.toLowerCase() 变为小写*/
/* 鼠标移入变小写 */
var ipt1 = ipt.nextElementSibling.nextElementSibling;
var ipt2 = ipt1.nextElementSibling.nextElementSibling;
ipt2.value = ipt2.value.toLowerCase() // 第三个input框内获得焦点字母变为小写
}
function sec(){
var ipt = document.querySelector('input')
var ipt1 = ipt.nextElementSibling.nextElementSibling;
/* ipt1.value = ipt1.value.charCodeAt() 第二个input框内输入的字母转换为ascll */
ipt1.value = ipt1.value.toLowerCase() // 第二个input框内输入的字母变为小写
/* 鼠标移入变大写 */
var ipt2 = ipt1.nextElementSibling.nextElementSibling;
ipt2.value = ipt2.value.toUpperCase() // 第三个input框内失去焦点字母变为大写
}
</script>
3.onmouseenter/onmouseleave案例
<style type="text/css">
p {
color: white;
}
#div {
width: 300px;
height: 250px;
background-color: #00FF00;
text-align: center;
}
.div1 {
width: 220px;
height: 80px;
background-color: red;
margin: 0 auto;
}
.div2 {
width: 220px;
height: 80px;
background-color: red;
margin: 20px auto;
}
</style>
</head>
<body>
<div id="div" onmouseenter="first();" onmouseleave="sec();">
<p>我是大盒子</p>
<div class="div1">
<p>我是小盒子1</p>
</div>
<div class="div2">
<p>我是小盒子2</p>
</div>
</div>
</body>
<script type="text/javascript">
var div = document.querySelector('#div');
function first() {
var r = parseInt(Math.random() * 256)
var g = parseInt(Math.random() * 256)
var b = parseInt(Math.random() * 256)
var rgb = 'rgb(' + r + ',' + g + ',' + b + ')';
div.style.backgroundColor = rgb;
}
function sec() {
div.style.backgroundColor = '#00FF00';
}
</script>
4.onmouseover/onmouseout案例
<style type="text/css">
p {
color: white;
}
#div {
width: 300px;
height: 250px;
background-color: #00FF00;
text-align: center;
}
.div1 {
width: 220px;
height: 80px;
background-color: red;
margin: 0 auto;
}
.div2 {
width: 220px;
height: 80px;
background-color: red;
margin: 20px auto;
}
</style>
</head>
<body>
<div id="div" onmouseover="first();" onmouseout="sec();">
<p>我是大盒子</p>
<div class="div1">
<p>我是小盒子1</p>
</div>
<div class="div2">
<p>我是小盒子2</p>
</div>
</div>
</body>
<script type="text/javascript">
var div = document.querySelector('#div');
function first() {
var r = parseInt(Math.random() * 256)
var g = parseInt(Math.random() * 256)
var b = parseInt(Math.random() * 256)
var rgb = 'rgb(' + r + ',' + g + ',' + b + ')';
div.style.backgroundColor = rgb;
console.log('进入大盒子');
}
function sec() {
div.style.backgroundColor = '#00FF00';
console.log('离开大盒子');
}
</script>
5.onkeypress/onkeydown/onkeyup案例
<body>
<input id="" value="" placeholder="onkeypress" onkeypress="press();" /><br>
<input id="" value="" placeholder="onkeydown" onkeydown="down();" /><br>
<input id="" value="" placeholder="onkeyup" onkeyup="up();" /><br>
<input id="" value="" placeholder="all" onkeypress="press();" onkeydown="down();" onkeyup="up();" /><br>
</body>
<script type="text/javascript">
var ipt = document.querySelector('input').value;
function press() {
console.log('我是onkeypress');
}
function down() {
console.log('我是onkeydown');
}
function up() {
console.log('我是onkeyup');
}
</script>
八.事件对象
1.什么是事件对象
任何事件触发后将会产生一个事件对象,跟事件相关的一系列信息数据的集合都放到这个对象里面
①谁绑定了这个事件
②如果是鼠标触发事件,会得到鼠标的相关信息,如鼠标位置
③如果是键盘触发事件,会得到键盘的相关信息,如按了哪个键
2.事件对象的获取
事件触发时就会产生一个事件对象,系统会以实参的形式将这个事件对象传给事件处理函数
<body>
<button type="button">何海杰</button>
</body>
<script type="text/javascript">
var btn = document.querySelector('button')
btn.onclick = function(event){ //这个event就是事件对象,经常写成e或者evt
console.log('是好人');
}
</script>
3.事件对象的属性和方法
属性和方法 | 说明 |
e.target | 返回事件源(标准浏览器) |
e.srcElement | 返回事件源(非标准浏览器,在 IE6~8 中) |
e.type | 返回事件类型 |
e.stopPropagation() | 阻止事件冒泡(标准浏览器) |
e.cancelBubble | 阻止事件冒泡(非标准浏览器,在 IE6~8 中,true) |
e.preventDefault() | 阻止默认事件(标准浏览器) |
e.returnValue | 阻止默认事件(非标准浏览器,在 IE6~8 中,false) |
1.e.target 和 this 的区别
在事件冒泡时,e.target指向的是子元素,因为他是触发事件的那个具体元素对象
this指向的是父元素,因为它是绑定事件的元素对象
<body>
<div id="div" style="width: 100px;height: 100px;background-color: orangered;">我是一个div
<button type="button">点一下</button>
</div>
</body>
<script type="text/javascript">
var div = document.querySelector('#div')
div.onclick = function(e) {
e = e || window.event;
console.log(e.target) //button元素 <button type="button">点一下</button>
console.log(this); //div元素 <div id="div" style="...;">…</div>
}
</script>
2.阻止事件冒泡
<title></title>
<style type="text/css">
#dad {
width: 200px;
height: 100px;
background-color: #00FFFF;
}
#son {
width: 100px;
height: 50px;
background-color: #00FF00;
margin: 10px auto;
}
</style>
</head>
<body>
<div id="dad">
大盒子
<div id="son">
小盒子
</div>
</div>
</body>
<script type="text/javascript">
var son = document.querySelector('#son');
son.onclick = function(e) {
console.log('点击了小盒子');
/* e.stopPropagation(); 标准浏览器阻止事件冒泡 */
/*
if(e && e.stopPropagation){
e.stopPropagation();
} else {
window.event.cancelBubble = true;
}
} 兼容阻止事件冒泡*/
window.event.cancelBubble = true; // 阻止事件冒泡
var dad = document.querySelector('#dad')
dad.onclick = function() {
console.log('你点击了大盒子');
}
}
</script>
3.阻止默认行为
<body>
<a href="http://www.baidu.com">百度</a>
</body>
<script type="text/javascript">
var a = document.querySelector('a')
a.onclick = function(e){
/* 兼容处理
if(e && e.preventDefault){
e.preventDefault();
} else {
wondow.event.returnValue = false;
}*/
/* window.event.returnValue = false; */
/* e.returnValue = false; */
/* e.preventDefault(); */
return false; // 阻止默认行为 一行代码搞定
}
</script>
禁止右键和选中内容
<body>
<h1>禁用鼠标右键</h1>
<h2>禁止选中内容</h2>
</body>
<script type="text/javascript">
document.oncontextmenu = function(e) {
e = e || window.event;
/* if (e && e.preventDefault) {
e.preventDefault();
} else {
e.returnValue = false;
} */
return false;
}
document.onselectstart = function(e) {
e = e || window.event;
/* if (e && e.preventDefault) {
e.preventDefault();
} else {
e.returnValue = false;
} */
return false;
}
</script>
禁用F12键
<script>
document.onkeydowm = function(e){
var current = e.keyCode || e.which || e.charCode;
e = e || window.event;
if(current == 123){
e.cancelBubble = true;
e.returnValue = false;
}
}
</script>
4.鼠标事件对象
鼠标事件对象属性 | 说明 |
e.clientX | 返回鼠标相对于浏览器窗口可视区的X坐标 |
e.clientY | 返回鼠标相对于浏览器窗口可视区的Y坐标 |
e.pageX | 返回鼠标相对于文档页面的X坐标(IE9+支持) |
e.pageY | 返回鼠标相对于文档页面的Y坐标(IE9+支持) |
e.ScreenX | 返回鼠标相对于电脑屏幕的X坐标 |
e.ScreenY | 返回鼠标相对于电脑屏幕的Y坐标 |
通过事件对象获取鼠标的坐标
<script type="text/javascript">
document.onclick = function(e){
e = e || window.event;
/* 电脑屏幕的 x 和 y */
console.log(e.screenX);
console.log(e.screenY);
/* 浏览器窗口可视区的 x 和 y */
console.log(e.clientX);
console.log(e.clientY);
/* 鼠标在文档页面的 x 和 y */
console.log(e.pageX);
console.log(e.pageY);
}
</script>
案例:跟随鼠标的蜜蜂
<body>
<img src="../../img/bee.gif" style="position: absolute;">
</body>
<script type="text/javascript">
var img = document.querySelector('img')
document.addEventListener('mousemove', function(e) {
e = e || window.event;
var x = e.clientX;
var y = e.clientY;
img.style.left = x - 70 + 'px';
img.style.top = y - 100 + 'px';
})
5.键盘事件对象的属性
keyCode:获得按键的ASCII值
<body>
<script type="text/javascript">
document.onkeydown = function(e){
console.log(e.keyCode); //返回大写的ascll码值
}
document.onkeyup = function(e){
console.log(e.keyCode); //返回大写的ascll码值
}
document.onkeypress = function(e){
console.log(e.keyCode); // 区分大小写,返回ascll码值
}
</script>
</body>
案例:搜索框获得鼠标焦点
<body>
<input type="" name="" id="" value="" />
</body>
<script type="text/javascript">
var ipt = document.querySelector('input')
document.onkeyup = function(e){
if(e.keyCode == 65){
ipt.focus() // 按下 a 键,input获得焦点
}else if(e.keyCode == 13){
ipt.blur() // 按下 enter 键,input失去焦点
}
}
//键盘事件,就是通过查询键盘的ascll值,
//来对键盘进行一系列的操作
</script>
九.事件委托
1.什么是事件委托
事件委托就是把事情委托给别人,代为处理。 事件委托说白了就是,不给子元素注册事件,给父元素注册事件,把处理代码在父元素的事件中执行。 事件委托是事件冒泡本身的特性,会带来的坏处,也会带来的好处。 事件委托也称为事件代理,在 jQuery 里面称为事件委派。
2.事件委托的作用
使用事件委托可以节约工作量并提高程序的性能。 比如一个ul下有多个li,现要求点击每个li都弹出对话框, 以前需要给每个li注册事件,相应地就要多次访问DOM,就会延长整个页面的交互就绪时间。 现在我们只要给ul注册事件,从而只需要操作一次 DOM ,这样就大大提高了程序的性能。
3.事件委托的使用
给父元素注册事件,利用事件冒泡,当子元素的事件触发,会冒泡到父元素,然后去控制相应的子元素。 具体如何去控制子元素呢,我们只要使用 e.target,就可以获取到事件源(比如点击的那个子元素),从而就可以对这个子元素进行操作了。
<body>
<ul style="cursor: default;">
<li>我是第一个</li>
<li>我是第二个</li>
<li>我是第三个</li>
<li>我是第四个</li>
<li>我是第五个</li>
</ul>
</body>
<script type="text/javascript">
var ul = document.querySelector('ul')
ul.addEventListener('click',function(e){
e.target.style.color = 'red'; // 点击哪一个li标签哪一个就会变色
})
</script>