jsの再体验 - - DOM事件高级

一、注册和解绑事件

1.1.传统注册和解绑事件方式
1.1.1.传统注册

事件源 . 事件类型 = function(){}

  • 特点:注册事件的唯一性
    同一个元素的同一个事件只能设置一个处理函数,最后注册的处理函数将会覆盖最前面注册的处理函数
<button>1</button>
<button>2</button>
<script>
    var btns=document.querySelectorAll('button')
    btns[0].onclick = function(){
        alert("hbsd1")
    }
    // 第一个被覆盖,只会执行第二个
    btns[0].onclick = function(){
        alert("hbsd2")
    }
</script>
1.1.2.传统解绑

事件源 . 事件类型 = null

btns[0].onclick = function(){
    alert("hbsd1")
    btns[0].onclick = null   // 传统方式解绑事件
}
1.2.方法监听注册和解绑方式
1.2.1.监听注册

事件源 . addEventListener('事件类型',function(){},false)

  • addEventListener():w3c标准推荐,IE9之前不支持,可以使用attachEvent()代替
  • 特点:同一个元素同一个事件可以注册多个监听器(function),按照顺序依次执行
addEventListener方法的参数解释
type事件类型,如click,mouseover(不用加on,而且是字符串类型,需要加引号)
listener事件处理函数(function)(监听器)
useCapture可选参数,默认false
<button>传统注册</button>
<button>监听注册</button>
<script>
    var btns=document.querySelectorAll('button')
    // 同一个元素 同一个事件可以添加多个监听器(事件处理程序)
    btns[1].addEventListener('click',function(){
        alert("监听注册1")
    })
    btns[1].addEventListener('click',function(){
        alert("监听注册2")
    })
</script>
1.2.2.监听解绑

事件源.removeEventListener('事件类型',函数名)
注意:事件处理函数不能使用匿名函数

// 如果后续需要解绑事件,事件处理函数不能使用匿名函数(必须写到外面),并且调用的时候不需要加括号
btns[1].addEventListener('click',fn1)  
function fn1(){
    alert("监听注册1")
    // removeEventListener解绑事件
    btns[1].removeEventListener('click',fn1)  
}
1.3.IE9以前的方法监听注册和解绑方式
1.3.1.监听注册

事件源.attachEvent(事件类型,回调函数):非标准,了解即可

addEventListener方法的参数解释
eventNameWithOn事件类型,如onclick,onmouseover(需要加on,而且是字符串类型,需要加引号)
callback事件处理函数(function)(回调函数)
btns[2].attachEvent('onclick',function(){
   alert("ie9前 监听注册")
})
1.3.2.监听解绑

事件源.detachEvent('on+事件类型',函数名)

btns[2].attachEvent('onclick',fn2)
function fn2(){
    alert("ie9前 监听注册")
    // removeEventListener解绑事件
    btns[2].detachEvent('onclick',fn2)  
}
1.4.兼容性封装注册和解绑函数
1.4.1.注册函数

兼容性处理原则:先照顾大多数浏览器,再处理特殊浏览器

<button>函数注册</button>
<script>
    var btns=document.querySelectorAll('button')
	function addEventListener(element,eventName,fn){
	   // 判断当前浏览器是否支持addEventListener方法
	   if(element.addEventListener){
	       element.addEventListener(eventName,fn)  // 第三个参数默认false
	   }else if(element.attachEvent){
	       element.attachEvent('on'+eventName,fn)  // ie9
	   }else{
	       element['on'+eventName]=fn              // 传统方式,相当于element.οnclick=fn
	   }
	}
	addEventListener(btns[3],'click',function(){alert("函数")})
</script>
1.4.2.解绑函数
function removeEventListener(element,eventName,fn){
   if(element.removeEventListener){
       element.removeEventListener(eventName,fn)   // 第三个参数是false
   }else if(element.detacEvent){
       element.detacEvent('on'+eventName,fn)
   }else{
       element['on'+eventName] = null
   }
}

二、DOM事件流

2.1.DOM事件流的3个阶段

事件流:描述从页面中接收事件的顺序
事件发生时会在元素节点中间按照特定的顺序传播,这个传播过程DOM事件流

  • DOM事件流的3个阶段
    1.捕获阶段:由最顶层DOM节点(Document)逐级向下传播到具体元素的过程(网景最早弹出)
    2.当前目标阶段:绑定事件的元素
    3.冒泡阶段:从事件源开始,逐级向上传播到DOM最顶层节点的过程(IE最早提出)
    请添加图片描述
2.2.DOM事件流3个阶段的验证
  • JS代码只能同时执行捕获或冒泡的一个阶段
  • addEventListener(事件类型,事件处理函数,第三个参数)
    第三个参数为true时,表示事件捕捉阶段调用事件处理程序
    捕获阶段 document - html - body - father - son从上至下
    第三个参数为false时,表示事件冒泡阶段调用事件处理程序
    冒泡阶段 son - father - body - html - document从下至上
  • onclick和attachEvent,只能得到冒泡阶段
  • onbulr、onfouse、onmouseover和onmouseleave,这些事件是没有冒泡的
  • 实际开发中很少关注事件捕获,更关注事件冒泡
<div class="father">
    <div class="son">son_div</div>
</div>
<script>
    var father = document.querySelector('.father')
    var son=document.querySelector('.son')

    // addEventListener的第三个参数为 true 为捕获阶段
    // 捕获阶段 document - html - body - father - son
    // 点击son的div 先弹出 father ,再弹出 son
    son.addEventListener('click',function(){alert('son')},true)
    father.addEventListener('click',function(){alert('father')},true)

    // addEventListener的第三个参数为 false 为冒泡阶段
    // 冒泡阶段 son - father - body - html - document
    // 点击son的div 先弹出 son ,再弹出 father
    son.addEventListener('click',function(){alert('son')},false)
    father.addEventListener('click',function(){alert('father')},false)

</script>

三、事件对象

事件源 . 事件类型 = function(event) {}

  • event是事件对象,存储一系列跟时间相关的信息数据集合,包含很多属性和方法
    若鼠标触发事件,会得到鼠标相关信息,如点击时鼠标的位置,鼠标按钮状态
    若键盘触发事件,会得到键盘相关信息,如按了键盘那个键
  • event是一个形参,由系统自动创建并设定为事件对象,无须传递实参,依次被传递给事件监听器
  • event可以自己设置,可以是 evt 或 e
  • 有兼容性问题,ie 6,7,8不识别,需要使用window.event来获取
    兼容性处理 e = e || window.event
3.1.事件对象的常见属性和方法
属性或方法说明
e.target返回触发事件对象(事件源,标准)
e.srcElement返回触发事件对象(非标准,ie6-8使用)
e.type返回事件类型(如click,mouseover,不带on)
e.preventDefault()阻止默认事件(如不让链接跳转)(标准)
e.returnValue阻止默认事件(如不让链接跳转)(非标准,ie6-8使用)
e.stopProgapation()阻止冒泡(标准)
e.cancelBubble阻止冒泡(非标准,ie6-8使用)
3.1.2.this 与 target 的区别

this:指向绑定事件的对象(元素)
e.target:指向触发事件的对象(元素)

<ul>
    <li>1</li>
    <li>2</li>
    <li>3</li>
</ul>
<script>
    // 给ul绑定事件,但点击的有可能是里面的小li
    // this返回的是ul,e.target返回的是被点击的小li
    var ul=document.querySelector('ul')
    ul.addEventListener('click',function(e){
        // 点击第2个小li
        console.log(this)             // 返回ul
        console.log(e.currentTarget)  // 返回ul(与this相似,但有兼容性问题,ie6-8不兼容)
        console.log(e.target)         // 返回第2个li
    })

    // ie6-8 兼容性处理 e 和 target
    ul.onclick = function(e){
        e = e || window.event
        var target = e.target || e.srcElement
        console.log(target)
    }
</script>
3.1.3.阻止默认事件
  • e.preventDefault() :方法
  • e.returnValue:属性
  • return false
<a href="http://www.baidu.com">百度</a>

<script>
    var a = document.querySelector('a')
    // 传统注册方式 阻止跳转 的3种方式
    a.onclick = function(e){
        e.preventDefault()   // 普通浏览器
        e.returnValue        // ie6-8浏览器
        return false         // 没有兼容性问题,但return后面的代码无法继续执行
    }
    
    // addEventListener注册方式 阻止跳转
    a.addEventListener('click',function(e){
        e.preventDefault()   // dom标准
    })
</script>
3.1.3.阻止事件冒泡
  • e.stopPropagation
  • event.cancelBubble = true
<script>
	// addEventListener的第三个参数为 false 为冒泡阶段
	// 冒泡阶段 son - father - body - html - document
	// 点击son的div 先弹出 son ,再弹出 father
	son.addEventListener('click',function(e){
	    alert('son')
	    if(e && e.stopPropagation){
	        e.stopPropagation()  // 停止冒泡,有兼容性问题
	    }else{
	        window.event.cancelBubble = true  // 停止冒泡,解决兼容性问题
	    }
	},false)
	father.addEventListener('click',function(){alert('father')},false)
	document.addEventListener('click',function(){alert('document')},false)
</script>
3.1.4事件委托(代理)
  • 原理(面试常问)将事件委托给当前操作元素的父节点(将事件监听器设置在其父节点上),再利用冒泡原理影响设置每个子节点(而不是给每个子节点单独设置事件监听器)
    案例:给ul注册点击事件,利用target找到当前点击的li,点击li会冒泡到ul上,ul上注册了事件,就会触发监听器
<!-- 事件委托 -->
<!-- 不给li设置点击事件,而给ul设置点击事件,通过点击li,然后冒泡到ul,触发ul绑定的事件 -->
<!-- 期间可以通过e.target获得被点击的li,并对li进行相关的样式和属性的操作 -->
<ul>
   <li>知否知否1</li>
   <li>知否知否2</li>
   <li>知否知否3</li>
   <li>知否知否4</li>
</ul>
<script>
   var ul=document.querySelector('ul')
   ul.addEventListener('click',function(e){
       // 将被点击的li背景颜色改成红色
       e.target.style.backgroundColor = 'red'
   })
</script>
3.1.5.禁止复制或选中文字
  • contextmenu:禁止右键复制文字
  • selectstart:禁止复制文字
<P>我是一段不愿意被分享的文字</P>
<script>
    var p=document.querySelector('p')
    // contextmenu 禁用触发右键菜单(禁止复制,但任然可以ctrl+c粘贴)
    p.addEventListener('contextmenu',function(e){
        e.preventDefault()   // 阻止选中文字后默认弹出的右键菜单
    })
    // selectstart 禁止文字被选中(可以禁止复制和粘贴)
    p.addEventListener('selectstart',function(e){
        e.preventDefault()
    })
</script>
3.2.鼠标事件对象MouseEvent
鼠标事件解释
onmouseover鼠标经过触发
onmouseout鼠标离开触发
onmousemove鼠标移动触发
onmouseup鼠标弹起触发
onmousedown鼠标按下触发
MouseEvent事件在页面中的坐标解释
e.clientX在可视区域内,获取鼠标点击处距离 浏览器 左边框的距离,滚动条滚动时距离不变
e.clientY在可视区域内,获取鼠标点击处距离 浏览器 上边框的距离,滚动条滚动时距离不变
e.pageX在可视区域内,获取鼠标点击处距离 文档 左边框的距离,滚动条滚动时距离不变,兼容性(IE9以上才支持)
e.pageY在可视区域内,获取鼠标点击处距离 文档 上边框的距离,滚动条滚动时距离不变,兼容性(IE9以上才支持)
e.screenX在可视区域内,获取鼠标点击处距离 电脑屏幕 左边框的距离,滚动条滚动时距离不变
e.screenY在可视区域内,获取鼠标点击处距离 电脑屏幕 上边框的距离,滚动条滚动时距离不变
<script>
    document.addEventListener('mousedown',function(e){
        console.log(e)           // 注意:click获取的是PointEvent,mousedown获取的是MouseEvent
        console.log(e.clientX)   // 在可视区域内,获取鼠标点击处距离 浏览器 左边框的距离,滚动条滚动时距离不变
        console.log(e.clientY)   // 在可视区域内,获取鼠标点击处距离 浏览器 上边框的距离
        console.log(e.pageX)     // 在可视区域内,获取鼠标点击处距离 文档 左边框的距离,跟着滚动条滚动的距离变化,兼容性(IE9以上才支持)
        console.log(e.pageY)     // 在可视区域内,获取鼠标点击处距离 文档 上边框的距离
        console.log(e.screenX)   // 在可视区域内,获取鼠标点击处距离 电脑屏幕 左边框的距离,当前浏览器窗口放大缩小会有影响
        console.log(e.screenY)   // 在可视区域内,获取鼠标点击处距离 电脑屏幕 上边框的距离
    })
</script>
3.3.键盘事件对象KeyBoardEvent
键盘事件说明
keydown键盘按下
keyup键盘弹起
keypress键盘按下(注意:不识别功能键,如ctrl shift 箭头等)
KeyBoardEvent键盘事件对象解释
keyCode获得的按下键的ASCII码值(keydown 和 keyup不区分大小写,keypress区分大小写)
// 三个事件的执行顺序,先keydown - keypress - keyup
// keydown 和 keyup 使用 keyCode 获得的按下键的ASCII码值 不区分大小写(都按小写走)
// keypress 使用 keyCode 获得的按下键的ASCII码值 区分大小写
document.addEventListener('keydown',function(e){
    console.log('down:'+e.keyCode)
})
document.addEventListener('keypress',function(e){
    console.log('press:'+e.keyCode)
})
document.addEventListener('keyup',function(e){
    console.log('up:'+e.keyCode)
})
3.5.1.键盘事件对象小案例
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值