JavaScript核心之DOM系列(二)
事件基础
JavaScript有能力创建动态页面,而事件是可以被JavaScript侦测到的行为。网页中的每个元素都可以产生某些可以触发 JavaScript 函数的事件,比如点击事件。
事件由三部分组成:
①事件源:事件被触发的对象(比如被点击的按钮)
②事件类型:如何触发的(什么事件)。比如点击、鼠标经过、键盘按下
③事件处理程序:事件触发后,做什么操作。采取函数赋值的方式
事件的执行步骤:获取事件源→注册事件→添加事件处理程序
常见的鼠标事件:
| onclick | 鼠标点击左键触发 |
| onmouseover | 鼠标经过触发 |
| onmouseout | 鼠标离开触发 |
| onfocus | 获得鼠标焦点触发 |
| onblur | 失去鼠标焦点触发 |
| onmousemove | 鼠标移动触发 |
| onmouseup | 鼠标弹起触发 |
| onmousedown | 鼠标按下触发 |
键盘事件:
|
onkeydown
|
按键被按下时触发 | 通过keycode属性获取相应键的ASCII码值,keyup和keydown事件不区分大小写,a和A都是65 |
| onkeyup | 按键被松开时触发 | |
| onkeypress | 按键被按下时触发(不能识别功能键,eg:Ctrl、shift、箭头等) | 通过keycode属性获取相应键的ASCII码值,keypress事件 区分字母大小写(A65 a97) |
执行顺序 keydown->keypress->keyup
注册事件
给元素添加事件,称为注册事件或者绑定事件。
注册事件的两种方式:传统方式和方法监听注册方式
| 传统方式 | 方法监听方式 |
| 利用on开头的事件,如onclick | 符合w3c标准(推荐),使用addEventListener()方法 |
| btn.onclick=function(){} | btn.addEventListener('click',function(){}) |
| 特点:注册事件的唯一性 | 特点:同一个元素同一个事件可以注册多个监听器(监听处理函数) |
| 同一个元素同一个事件只能设置一个处理函数 | 按注册顺序依次执行 |
| 后注册的处理函数会覆盖前面注册的处理函数 | 注:IE9前不支持,可使用attachEvent()代替 |
传统方式的注册事件:
<button id="btn">唐伯虎</button>
<script>
// 点击按钮 弹出对话框
// 1.获取事件源
var btn=document.getElementById('btn');
// 2.事件类型 点击(onclick)
// 3.事件处理程序 通过一个函数赋值的方式
btn.onclick=function(){
console.log(btn.innerText);
alert('点秋香')
}
</script>
语法:eventTarget.addEventListener(type,listener[,useCapture])
type:监听事件类型字符串,比如:click、mousemove,注意这里不要带on
listener:事件处理函数。事件发生时,会调用该监听函数
useCapture:可选参数。Boolean,设为true时,沿着DOM树向上冒泡的事件,不会触发listener。默认为false
<button>方法监听注册方式</button> <script> var btn=document.querySelector('button'); btn.addEventListener('click',function(){ alert("11"); }); </script>
注册事件兼容性解决方案
<script>
function addEventListener(element,eventName,fn){
if(element.addEventListener){
element.addEventListener(eventName,fn);
}else if(element.attachEvent){
element.attachEvent('on'+eventName,fn);
}else{
element['on'+eventName]=fn;
}
}
<script>
兼容性处理原则:先照顾大多数浏览器,再处理特殊浏览器
删除事件(解绑事件)
| 传统方式注册的事件解绑 | 方法监听注册方式解绑 |
| eventTarget.onclick=null | eventTarget.removeEventListener(type,listener[,useCapture]) |
DOM事件流
事件发生时,会在元素节点之间按照特定的顺序传播,这个传播过程即DOM事件流
DOM事件流分为3个阶段:捕获阶段、当前目标阶段、冒泡阶段
eg:div的点击事件

事件冒泡:事件开始由最具体的元素接受,然后逐层向上传播到DOM最顶节点的过程 (IE最早提出)
事件捕获:由DOM最顶节点开始,逐层向下传播到最具体的元素接收过程 (网景最早提出)
| 捕获阶段 | 冒泡阶段 |
<style> .father{ width: 300px; height: 300px; background-color: green; } .son{ width: 150px; height: 150px; background-color: yellowgreen; margin: 0 auto; } </style> <div class="father"> <div class="son">son盒子</div> </div> <script> // js 代码中只能执行捕获或者冒泡其中一个阶段 // onclick和attachEvent(ie)只能得到冒泡阶段 // 捕获阶段 如果addEventListener // 第三个参数为true,处于捕获阶段 执行顺序document ->html->body->father->son var son=document.querySelector('.son') son.addEventListener('click',function(){ alert('son') // 后出 },true) var father=document.querySelector('.father') father.addEventListener('click',function(){ alert('father') // 先出 },true) </script>
|
<style> .father2{ width: 300px; height: 300px; background-color: green; } .son2{ width: 150px; height: 150px; background-color: yellowgreen; margin: 0 auto; } </style> <div class="father2"> <div class="son2">son2盒子</div> </div> <script> // 冒泡阶段 如果addEventListener第三个参数为false(不写 默认是false) // ,处于冒泡阶段 son2->father2->body->html->document var son=document.querySelector('.son2') son.addEventListener('click',function(){ alert('son2') // 先出 }) var father=document.querySelector('.father2') father.addEventListener('click',function(){ alert('father2') // 后出 }) // var father=document.querySelector('.father') document.addEventListener('click',function(){ alert('document') // 最后出 }) </script>
|
实际开发中,很少使用事件捕获,更关注的是事件冒泡。
注:有些事件没有冒泡,比如:onblur\onfocus\onmouseenter\onmouseleave
事件对象
事件对象是事件的一系列相关数据的集合
比如:鼠标触发事件,得到鼠标的相关信息(如 鼠标的位置)
键盘触发事件,得到键盘的相关信息(如 按了哪个键)
看下面代码:
<div></div>
<script>
// 事件对象
var div=document.querySelector('div');
div.onclick=function(event){
console.log(event);// 普通浏览器
console.log(window.event); // ie6-8
console.log(event||window.event);// 兼容性写法
}
</script>
上面代码中,event就是一个事件对象。有了事件才会有事件对象,是系统自动创建的,无需传参。
这个事件对象可以自己命名,一般为event、evt、e等等。
注:事件对象也有兼容性问题 ie678 通过window.event获取
事件对象的常见属性方法
| e.target | 返回触发事件的对象 | 标准 |
| e.srcElement | 返回触发事件的对象 | 非标准 ie6-8 |
| e.type | 返回事件类型(如click、mouseover) | 不带on |
| e.cancelBubble | 阻止冒泡 | 非标准 ie6-8 |
| e.returnValue | 阻止默认事件(默认行为,比如 不允许a链接跳转) | 非标准 ie6-8 |
| e.preventDefault | 标准 | |
| e.stopPropagation | 阻止冒泡 | 标准 |
注:e.target与this的区别
e.target返回的是触发事件的对象(元素)
this返回的是绑定事件的对象(元素)
代码如下:
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
</ul>
<script>
var ul=document.querySelector('ul');
// this指向的是绑定事件的对象 元素
// e.target指向的触发事件的对象 元素
ul.addEventListener('click',function(e){
console.log(this); // 返回<ul><li>……</ul>
console.log(e.target); //返回 点击的li <li>2</li>
});
</script>
阻止默认行为:
<a href="http://www.baidu.com">百度</a>
<script>
// 阻止默认行为(事件),让链接不跳转、或者提交按钮不提交
var a=document.querySelector('a')
// a.addEventListener('click',function(e){
// e.preventDefault()
// })
a.onclick=function(e){
// 普通浏览器 preventDefault()方法
// e.preventDefault();
// 低版本浏览器 ie6-8 returnValue属性
// e.returnValue
// 也可以用return false 阻止默认行为 没有兼容性问题
return false
}
</script>
阻止事件冒泡
<style> .father{ width: 300px; height: 300px; background-color: green; } .son{ width: 150px; height: 150px; background-color: yellowgreen; margin: 0 auto; } </style> <div class="father"> <div class="son">son盒子</div> </div> <script> var son=document.querySelector('.son'); var father=document.querySelector('.father'); son.addEventListener('click',function(e){ alert('son') // 先出 // 阻止事件冒泡 父级的弹框不生效 e.stopPropagation() // e.cancelBubble=true // 兼容ie6-8 }); father.addEventListener('click',function(){ alert('father') // 后出 }); // var father=document.querySelector('.father') document.addEventListener('click',function(){ alert('document') // 最后出 }); </script>
事件委托
利用事件冒泡本身的特性,只指定一个事件处理程序,就可以管理某一类型的所有事件。
就是说,如果我们有许多以类似方式处理的元素,那么就不必为每个元素分配一个处理程序,而是把事件监听器设置在它们的父元素上。
应用场景:当前被点击的li为红色
<ul>
<li>知否知否1</li>
<li>知否知否2</li>
<li>知否知否3</li>
<li>知否知否4</li>
<li>知否知否5</li>
</ul>
<script>
var ul = document.querySelector('ul')
ul.addEventListener('click', function(e) {
console.log(e.target);
var li = ul.children
for (let i = 0; i < li.length; i++) {
li[i].style.color = ''
}
e.target.style.color = 'red'
})
</script>

浙公网安备 33010602011771号