注册事件(绑定事件)
注册事件有两种方式:
- 传统方式
- 方法监听注册方式
传统注册方式
- 利用on开头的事件
- btn.onclick=function(){};
- 特点:注册事件的唯一性
- 即同一个元素同一个事件只能设置一个处理函数,最后注册的处理函数会覆盖前面注册的处理函数。
方法监听注册方式(推荐)
- w3c标准
- addEventListener()它是一个方法
- IE9之前不支持上面的方法,可使用arrachEvent()代替(这句话可以忽略)
- 特点:同一个元素用一个事件可以注册多个监听器(处理函数)
- 按注册顺序依次执行
addEventListener事件监听方式
目标对象.addEventListener(type,listener[ , useCapture])
- type:事件类型字符串。比如click、mouseover等
- listener:事件处理函数,事件发生时,会调用该监听函数
- useCapture:可选参数,布尔值,下面的事件流会用
<script> var btn=document.querySelector('button'); // 同一个元素可以注册多个监听器(处理函数) btn.addEventListener('click',function(){ alert('广告1'); }) btn.addEventListener('click',function(){ alert('广告2'); }) </script>
删除事件
删除事件的方式
传统注册方式的删除事件
eventTarget.onclick=null;
方法监听注册方式的删除事件
eventTarger.removeEventListener(type, listener[ , useCapture]);
<script> var divs=document.querySelectorAll('div'); div[0].onclick=function(){ alert('广告'); //传统方式删除事件 div.onclick=null; } div[1].addEventListener('click',fn);//里面的fn调用不需要加小括号 function fn(){ alert('广告'); //方法监听方式删除事件 div[1].removeEvnetListener('click',fn); } </script>
DOM事件流
事件流描述的是从页面中接收事件的顺序。
事件发生时会在元素节点之间按照特定的顺序传播,这个传播过程就是DOM事件流。
比如给一个div注册了点击事件,然后dom事件流就分为了3个阶段:
- 捕获阶段
- 当前目标阶段
- 冒泡阶段
形象比喻:我们向水里扔一块石头,首先它会有一个下降的过程,这个过程就可以理解为从最顶层向事件发生的最具体元素(目标点)的捕获过程;之后会产生泡泡,会在最低点(最具体的元素,即目标点)之后漂浮到水面上,这个过程相当于事件冒泡。
注意:
- js代码中只能执行捕获或者冒泡其中的一个阶段
- onclick和attchEvent只能得到冒泡阶段
- addEventListener(type, listenr[ , useCapture])第三个参数如狗是true,表示在事件捕获阶段调用事件处理程序,如果是false(不写默认就是false),表示在事件冒泡阶段调用事件处理程序。
- 实际开发中很少使用事件捕获,更多使用事件冒泡。
- 有些事件是没有冒泡,比如onblur、onfocus、onmouseenter、onmouseleave
<div class="father"> <div class="son">son盒子</div> </div> <script> // dom 事件流 三个阶段 // 1. JS 代码中只能执行捕获或者冒泡其中的一个阶段。 // 2. onclick 和 attachEvent(ie) 只能得到冒泡阶段。 // 3. 捕获阶段 如果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); // 4. 冒泡阶段 如果addEventListener 第三个参数是 false 或者 省略, // 那么则处于冒泡阶段 son -> father ->body -> html -> document var son = document.querySelector('.son'); son.addEventListener('click', function() { alert('son'); }, false); var father = document.querySelector('.father'); father.addEventListener('click', function() { alert('father'); }, false); document.addEventListener('click', function() { alert('document'); }) </script>结果演示
事件对象
btn.onclick=function(event){ console.log(event); //兼容性方法 //e=e||window.event; //console.log(e); }//event就是一个事件对象,写到监听函数的小括号里,当形参看。
- 事件对象只有有了事件才会存在,它是系统自动创建的,不需要我们传递参数。
- 事件对象是我们事件的一系列相关数据的集合,跟事件相关的,比如鼠标点击,event里面就包含了鼠标的相关信息:鼠标坐标等,如果是键盘事件,event里面就包含了键盘事件的信息:判断用户按下了哪个键等等。
- 事件对象可以自己命名
- 兼容性:IE678通过window.event 获取事件对象
event.target与this的区别
- event.target点击了哪个元素,就返回哪个元素
- this:哪个元素绑定了这个点击事件,就返回哪个元素
事件对象属性方法
阻止默认事件
- 普通浏览器 e.preventDefault() 最常用了
- 低版本浏览器 e.returnValue;
阻止事件冒泡
标准写法:
利用事件对象里面的event.stopPropagetion()方法
非标准写法:IE678:
利用事件对象event.cancelBubble=true;
阻止事件冒泡的兼容性解决方案
<script> if(enevt && event.stopPropagation){//如果有这个事件对象,并且可以识别这个方法 event.stopPropagation(); }else{ window.enevt.cancelBubble=true; } </script>
事件委托(代理、委派)
原理:
不是每个子节点都单独设置事件监听器,而是事件监听器设置在其父节点上,然后利用冒泡原理影响设置的每一个子节点。
作用:只操作了一次DOM,提高了程序的性能。
举例:
给ul注册点击事件,然后利用事件对象的target来找到当前点击的li,因为点击li,事件会冒泡到ul上,ul已经注册(绑定)了事件,就会触发事件监听器
<!-- <ul> <li>点我</li> <li>点我</li> <li>点我</li> <li>点我</li> </ul> --> <script> //事件委托的原理:给父节点添加监听器,利用事件冒泡影响每一个子节点 var ul=document.querySelector('ul'); ul.addEventListener('click',function(e){ alert('哈哈'); e.target.style.backgroundColor='blue'; }) </script>结果演示
常用的鼠标事件
方法监听注册方式的鼠标事件不写前面的on,键盘事件亦是如此。
mouseenter和mouseover的区别
- 当鼠标移动到元素上时就会触发mouseenter事件
- mouseover:鼠标经过自身盒子会触发,经过子盒子也会触发
- mouseenter:只会经过自身盒子触发
- 之所以这样,是因为mouseennter不会冒泡
- 跟mouseenter搭配的 鼠标离开 mouseleave 同样也不会冒泡
鼠标事件对象
案例
做一个跟随鼠标的图片,分析如下:
- 鼠标不断的移动,使用鼠标移动事件;mousemove
- 在页面中移动,给document注册事件
- 图片要移动距离,而且不占位置,则可以使用绝对定位
- 每次鼠标移动,都会获得最新的坐标,把这个x和y坐标作为图片的top和left值就可以移动图片
<script> var div=document.querySelector('div'); document.addEventListener('mousemove',function(e){ var x=e.pageX; var y=e.pageY; div.style.left=x+'px'; div.style.top=y+'px'; }) </script>结果演示
禁止鼠标右键菜单
contextmenu主要控制应该何时显示上下文菜单,即禁用右键菜单
document.addEventListener('contextmenu',function(e){ e.preventDefault();//阻止默认事件 })
禁止鼠标选中(选中文字)
selectstart 开始选中
document.addEventListener('selectstart',function(event){ event.preventDefault(); })
常用的键盘事件
- 只是onkeypress不识别功能键,比如ctrl、shift等。
- onkeyup和keydow事件不区分字母大小写,a和A的得到的都是65
- onkeypress事件区分字母大小写,a 97和A 65。
同时写三个事件的执行顺序:keydow—keypress—keyup
键盘事件对象
- e.keyCode 返回该键的ASCII值。
光标定位到搜索框案例
思路:
- 检测用户是否按下了a键,如果按下了a键,就把光标定位到搜索框里
- 使用keyCode判断用户是否按下了a键
- 搜索框获得焦点:使用js里的focus()方法
<script> var ip=document.querySelector('input'); document.addEventListener('keyup',function(e){ console.log(e.keyCode); if(e.keyCode === 65){ ip.focus(); } }) </script>结果演示
搜索框显示隐藏案例
分析:
- 快递单号输入内容时, 上面的大号字体盒子(con)显示(这里面的字号更大)
- 表单检测用户输入: 给表单添加键盘事件
- 同时把快递单号里面的值(value)获取过来赋值给 con盒子(innerText)做为内容
- 如果快递单号里面内容为空,则隐藏大号字体盒子(con)盒子
<script> var ip=document.querySelector('input'); var con=document.querySelector('.con'); ip.addEventListener('keyup',function(e){ //没有内容了就隐藏 if(this.value == ''){ con.style.display='none'; }else{ con.style.display='block'; con.innerText=this.value; } }) // 失去焦点,就隐藏这个con盒子 ip.addEventListener('blur',function(){ con.style.display='none'; }) // 获得焦点,就显示这个con盒子 ip.addEventListener('focus',function(){ // 然后有内容才会真的显示 if(this.value !== ''){ con.style.display='block'; } }) </script>结果演示