JavaScript DOM 事件进阶
Posted YuLong~W
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JavaScript DOM 事件进阶相关的知识,希望对你有一定的参考价值。
文章目录
事件
事件注册
传统方式
dom对象.事件名=事件处理程序
唯一性:同一个对象的同一个事件只能注册一个处理程序,后面注册的程序会将前面注册的程序覆盖掉
事件监听方式
由于不同浏览器采用的事件流实现方式不同,事件监听的实现存在兼容性问题。通常根据浏览器的内核,可以把浏览器划分为两大类
① 标准浏览器(W3C)
eventTarget.addEventListener(type, callback, [capture])
- type:dom对象绑定的事件类型,如click、change、focus 不带on
- callback:事件的处理程序
- [capture]:可选参数,指定事件处理方式。默认为false,表示冒泡阶段完成事件处理,true为捕获阶段完成事件处理(事件流中详讲)
② 早期IE内核浏览器(如IE 6~IE 8)
eventTarget.attachEvent(type, callback)
- type:onclick、onfocus 要带on
- callback同上:
不唯一性:给同一个DOM对象的同一个事件添加多个事件处理程序
注册事件兼容性解决代码:
function addEventListener(element, eventName, fn) {
// 判断当前浏览器是否支持 addEventListener 方法
if (element.addEventListener) {
element.addEventListener(eventName, fn); // 第三个参数 默认是false
} else if (element.attachEvent) {
element.attachEvent('on' + eventName, fn);
} else {
// 相当于 element.onclick = fn;
element['on' + eventName] = fn;
}
事件删除
- 传统:eventTarget.οnclick=null
- 早期:eventTarget.detachEvent(type,callback)
- 标准:eventTarget.removeEventListener(type,callback)
删除事件兼容性解决代码:
function removeEventListener(element, eventName, fn) {
// 判断当前浏览器是否支持 removeEventListener 方法
if (element.removeEventListener) {
element.removeEventListener(eventName, fn); // 第三个参数 默认是false
} else if (element.detachEvent) {
element.detachEvent('on' + eventName, fn);
} else {
element['on' + eventName] = null;
}
DOM事件流
事件流:指当事件发生时,会在发生事件的元素节点与DOM树根节点之间按照特定的顺序进行传播,这个过程称之为事件流
- 网景公司:采用事件捕获方式
- 微软公司:采用事件冒泡方式
- W3C:先捕获(但不处理),后冒泡(逐级处理)
事件冒泡: IE 最早提出,事件开始时由最具体的元素接收,然后逐级向上传播到到 DOM 最顶层节点的过程
事件捕获: 网景最早提出,由 DOM 最顶层节点开始,然后逐级向下传播到到最具体的元素接收的过程
- JS 代码中只能执行捕获或者冒泡其中的一个阶段
- onclick 和 attachEvent 只能得到冒泡阶段
- addEventListener(type, callback, [capture]) 第三个参数如果是true,表示在事件捕获阶段调用事件处理程序;如果是 false(不写默认就是false),表示在事件冒泡阶段调用事件处理程序
- 有些事件是没有冒泡的,比如 onblur、onfocus、onmouseenter、onmouseleave
事件对象
事件对象的使用
事件对象:event
当事件发生后,由系统自动生成,跟事件相关一系列信息数据的集合存放在event对象中,不需传递参数
- 早期IE内核浏览器:var 事件对象 = window.event
- W3C内核浏览器:dom对象.事件 =function (event) { }
事件对象的兼容性解决:
e=e||window.event;
常用属性和方法
e.target和this区别
- e.target返回的是触发事件的对象
- this返回的是绑定事件的对象
了解: this有个类似写法:e.currentTarget (兼容性不常用)
<ul>
<li></li>
<li></li>
<li></li>
</ul>
<script>
var ul=document.querySelector('ul');
ul.addEventListener('click',function(e){
console.log(this); //返回ul对象
console.log(e.target); //返回li对象
});
</script>
e.target支持IE9以上,处理兼容性问题:
div.onclick = function(e) {
e = e || window.event;
var target = e.target || e.srcElement;
console.log(target);
}
阻止默认行为
利用事件对象的preventDefault()方法和returnValue属性,禁止所有浏览器执行元素的默认行为
注意: 只有事件对象的cancelable属性设置为true,才可以使用preventDefault()方法取消其默认行为
阻止默认行为案例:
注册click事件,阻止a标签默认事件
<a href="http://www.baidu.com">百度</a>
<script>
var a = document.querySelector('a')
//标准浏览器
a.addEventListener('click', function (e) {
e.preventDefault()
})
a.onclick = function (e) {
//普通浏览器
e.preventDefault()
//低版本浏览器
e.returnValue
}
</script>
阻止事件冒泡
利用事件对象调用stopPropagation()方法和设置cancelBubble属性,实现禁止所有浏览器的事件冒泡行为
- 标准浏览器:e.stopPropagation()
- 非标准浏览器: e.cancelBubble = true
兼容性解决代码:
if(e && e.stopPropagation){
e.stopPropagation();
}else{
window.event.cancelBubble = true;
}
事件委托
原理: 不给子元素注册事件,而是给父元素注册事件监听器,利用 冒泡原理 影响到每个子元素
优点: 事件处理代码在父元素的事件执行。只操作了一次dom,提高了程序的性能
事件委托案例:
思路:给 ul 注册点击事件,然后利用事件对象的 target 来找到当前点击的 li,因为点击 li,事件会冒泡到 ul 上, ul 有注册事件,就会触发事件监听器
<ul>
<li>A</li>
<li>B</li>
<li>C</li>
<li>D</li>
<li>E</li>
</ul>
<script>
var ul = document.querySelector('ul')
ul.addEventListener('click', function (e) {
e.target.style.backgroundColor = 'pink'
})
</script>
鼠标事件
1、禁止鼠标右击菜单:contextmenu
document.addEventListener('contextmenu', function (e) {
e.preventDefault();
})
2、禁止鼠标选中:selectstart
document.addEventListener('selectstart', function (e) {
e.preventDefault();
})
鼠标事件对象
MouseEvent:和鼠标事件相关的一系列信息集合,用来获取当前鼠标的位置信息
IE 6~IE 8浏览器中不兼容pageX和pageY属性,在项目开发时需要对IE 6~IE 8浏览器进行兼容处理
var pageX = event.pageX || event.clientX +
(document.body.scrollLeft || document.documentElement.scrollLeft)
var pageY = event.pageY || event.clientY +
(document.body.scrollTop || document.documentElement.scrollTop)
鼠标事件案例:图片跟随鼠标移动
<style>
img{
width: 200px;
height: 180px;
position: absolute;
top: 2px;
}
</style>
<body>
<img src="./0.jpg" alt="">
<script>
var pic = document.querySelector('img')
document.addEventListener('mousemove', function (e) {
var x = e.clientX
var y = e.clientY
//确保鼠标位于图片最中间 都减去图片长宽一半
//加单位px
pic.style.left = x -100+ 'px'
pic.style.top = y -90+ 'px'
console.log('(x:' + x + ',y:' + y + ')')
})
</script>
</body>
键盘事件
注意:
- 如果使用addEventListener 不需要加 on ,而普通注册事件需要加on
- keypress和前面2个的区别是,它不识别功能键,比如左右箭头,shift 。ctrl等
- 三个事件的执行顺序是:keydown — keypress — keyup
三者的区别:
- keypress事件保存的按键值是ASCII码
- keydown和keyup事件保存的按键值是虚拟键码
- keydown和keypress如果按住不放的话,会重复触发该对应事件
- keyup和keydown事件不区分字母大小写,keypress区分字母大小写
键盘事件对象
KeyBoardEvent对象:是跟键盘事件相关的一系列信息的集合
keyCode属性:可以得到相应的ASCII码值,进而判断用户按下了哪个键
ASCII表:
键盘事件案例:输出用户按下的键
<body>
搜索: <input type="text">
<script>
var search = document.querySelector('input')
document.addEventListener('keyup', function (e) {
if (e.keyCode === 83) {
search.focus()
}
var n = String.fromCharCode(e.keyCode)
alert('你按了' + n + '键')
})
</script>
</body>
综合案例:快递单号放大显示
实现功能:input输入框内容同步显示到上方的方框中 并且失去焦点消失,获得焦点则出现
<style>
* {
margin: 0;
padding: 0;
}
.search {
position: relative;
width: 178px;
margin: 100px;
}
.con {
display: none;
position: absolute;
top: -40px;
width: 171px;
border: 1px solid rgba(0, 0, 0, .2);
box-shadow: 0 2px 4px rgba(0, 0, 0, .2);
padding: 5px 0;
font-size: 18px;
line-height: 20px;
color: #333;
}
.con::before {
content: '';
width: 0;
height: 0;
position: absolute;
top: 28px;
left: 18px;
border: 8px solid #000;
border-style: solid dashed dashed;
border-color: #fff transparent transparent;
}
</style>
<body>
<div class="search">
<div class="con">123</div>
<input type="text" placeholder="请输入您的快递单号" class="jd">
</div>
<script>
var con=document.querySelector('.con');
var input=document.querySelector('.jd');
//注册keyup事件 不能用keydown和keypress
input.addEventListener('keyup',function(){
if(this.value==''){
con.style.display='none';
}else{
con.style.display='block';
con.innerText=this.value;
}
});
//失去焦点
input.addEventListener('blur',function(){
con.style.display='none';
})
//获得焦点
input.addEventListener('focus',function(){
if(this.value!==''){
con.style.display='block';
}
});
</script>
</body>
以上是关于JavaScript DOM 事件进阶的主要内容,如果未能解决你的问题,请参考以下文章
更改页面javascript代码(TamperMonkey)以将键盘笔触发送到父DOM