这一概念源自于对事件触发对象的思考。例如常见的点击事件,鼠标移动事件。这些事件发生之时,往往不只是点击或者移动到某一特定元素上。
比如点击某一个按钮,而它是由上一层的父标签,或许在上一层还有父标签甚至是整个页面。因此点击一个元素可以看成是同时点击了父标签或者整个页面。那么此时事件应该怎么响应到指定标签呢?
即事件从指定元素开始传播到最外层的元素,并且该事件不仅会在指定元素上发生,还会在传播过过程中的每一个元素上发生。
<html>
<body>
<div>
<button>click</button>
</div>
</body>
</html>
如上,再点击click之后,事件从 button 开始传播至 html ,再到 documet。这一个过程也称为事件冒泡
与事件冒泡刚好相反,事件从最外层的 documet 开始一直往里面,直到点击的元素才停止
<html>
<body>
<div>
<button>click</button>
</div>
</body>
</html>
如上,再点击click之后,事件从 documet 开始传播至 button。这一个过程也称为事件捕获
在上述两种事件确定的方式下,规定了事件处理的三个阶段。事件捕获阶段、处于目标阶段、事件冒泡阶段。同时 DOM明确规定
主要是指 DOM 如何处理各种 HTML 上的程序。
对于所有浏览器来说,有两种标准用来操作事件的添加与删除,一种是 DOM2 事件处理程序,一种是 IE 事件处理程序。
直接调用该 dom 对象的事件属性,并将相应的执行函数赋予它
利用 dom 对象的事件属性直接赋予一个执行函数;利用 addEventListener 添加,并且该方法可以添加多个
addEventListener() 有三个参数,参数 1 为事件、参数 2 为执行函数。参数 3 为一个布尔值,false 代表在冒泡阶段执行,true 表示在捕获阶段执行
var doc = document.querySelector('div');
doc.onclick = function() {
alert(1);
}
doc.addEventListener('click', function() {
alert(2);
}, false)
doc.addEventListener('click', function() {
alert(3);
}, false)
利用直接设置事件属性为 null 来移出执行函数。利用 removeEventListener() 来移出,但前提是必须给定函数名
removeEventListener() 有三个参数,参数 1 为事件、参数 2 为执行函数。参数 3 为一个布尔值,false 代表在冒泡阶段执行,true 表示在捕获阶段执行
如下使用匿名函数定义的执行函数无法删除
var doc = document.querySelector('div');
doc.addEventListener('click', function() {
alert(2);
}, false)//通过匿名函数定义的
doc.removeEventListener('click',function() {
alert(2);
}, false);//无效
doc.onclick = null;//有效
function Click() {
alert(2);
}
doc.addEventListener('click', Click, false)//
doc.removeEventListener('click', Click, false);//有效
和 DOM 2 级一样用来添加事件,只有两个参数 "事件" 和 "处理函数",不能设置冒泡或者捕获。因为 IE8 之前那只支持冒泡,所以就只能冒泡
同样可以添加多个执行函数
和 DOM2 级一样,要删除必须给定函数名作为参数。无法删除通过匿名定义添加的执行函数。
因为 IE 独树一帜,又因为 IE 属于 windows 用户标配;所以兼容需要考虑。否则代码在 IE 上可能出问题
const EventHandle = {
addEvent: (element, type, fn) => {
if(element.addEventListener) {
element.addEventListener(type, fn, false);
} else if(element.attachEvent) {
element.attachEvent(type, fn);
} else {
element[`on${type}`] = fn;
}
},
removeEvent: (element, type, fn) => {
if(element.removeEventListener) {
element.removeEventListener(type, fn, false);
} else if(element.detachEvent) {
element.detachEvent(type, fn);
} else {
element[`on${type}`] = null;
}
},
}
let doc = document.querySelector('div');
function T() {
alert(13);
}
EventHandle.addEvent(doc, 'click', T);
EventHandle.removeEvent(doc, 'click', T);
事件对象作为事件发生给予 js 获得相关信息的机会非常重要。程序要根据这些信息作出相应的响应。
必定会传一个 event 对象给执行函数。可以直接作为参数使用。但有两种情况需要注意
<div onclick="Test(event)"></div>
<script>
function Test(event) {
console.log(event.type);
}
</script>
let doc = document.querySelector('header');
doc.addEventListener('click', function(event) {
console.log(event.target.tagName,event.type);
}, false);
这里的 currentTarget 是指发生事件时,该事件所绑定的那个元素
而 target 从始至终就都是你点击或者移动或者其他触发事件行为的元素
<div onclick="father(event)">
<button>1</button>
<button onclick="son(event)">2</button>
</div>
<script>
function father(event) {
console.log(event.target, event.currentTarget);
}
function son(event) {
console.log(event.target, event.currentTarget);
}
</script>
看上述这个例子。
另外,执行函数中的 this 值指向 currentTarget;但是有个前提,this值要等于 currentTarget,那么必须是在target上或者事件是通过 sddEventListener 添加的。否则通过html元素直接绑定的方式this指向了 window 对象
eventPhase 可以知道事件执行时处于哪个阶段
stopPropagation 可以阻值事件继续冒泡传播。我们知道一般事件是在处于目标阶段到冒泡阶段执行的。倘若不阻止冒泡,那么点击一个小按钮,一直回溯到 document。那么整个页面许多地方的点击事件都会触发,很显然我们不想这样。
<div onclick="father(event)">
<button>1</button>
<button onclick="son(event)">2</button>
</div>
<script>
function father(event) {
console.log(event.target, event.currentTarget);
}
function son(event) {
console.log(event.target, event.currentTarget, event.eventPhase);//button button 2
event.stopPropagation();//阻止继续冒泡。这样就不会触发 father 了
}
</script>
当然该方法同样可以阻止捕获,不过前提是绑定事件时指定他在捕获阶段触发。这样一来就不会继续捕获下去了
为什么不能统一呢,非要学两套
IE 事件对象与 DOM 级有一定差异
IE 中的 event 对象时作为 window 对象的一部分存在,可以通过 window.event 来获取
var doc = document.querySelector('#id');
doc.onclick = function (event) {
console.log(event.type);//event undefined
var event = window.event;
console.log(event.type);//click
}
doc.attachEvent('click', function(event) {
console.log(event.type);//click
});
执行函数中关于事件元素的信息都可以通过 event 获取,虽然 this 值有时也会等于 event 的部分属性。但是建议用 event,因为 this 的指向取决于外部执行环境,不能保证得到想要的值。
另外,IE 要没了。取而代之的是微软新浏览器 Edge ,这个浏览器好像已经统一了 DOM级规定的事件处理。原来 IE 的那些特有事件处理已经没有了
常见的事件类型
界面发生的事件
当页面完全加载,包括所有图像、js 文件、产生式文件等外部资源。之后就会触发该事件。添加事件的方法?建议使用之前写的跨浏览器事件处理方法。当然也可以通过获取 dom 对象,并对其属性赋值,也可以直接在 html 元素上绑定。但是这两个方法下的 event 对象的使用有区别,特别是在 IE 浏览器上
window.addEventListener('load', function(event) {
console.log(event.target, '加载完毕');
})
绑定事件后,设置 img 的 src 即刻加载。可以用来做图片的预加载。
let image = new Image();
image.addEventListener('load', function(event) {
console.log(event.target, '图像加载完毕');
})
window.addEventListener('load', function(event) {
console.log(event.target, '页面加载完毕,开始加载图像');
image.src = `https://timgsa.baidu.com/jz.jpg`;
})
let js = document.createElement('script');
js.addEventListener('load', function(event) {
console.log(event.target, 'js加载完毕');
})
window.addEventListener('load', function(event) {
console.log(event.target, '页面加载完毕,开始加载js');
js.src = `./xxx.js`;
})
与 load 事件相反,一般页面切换后触发,可用来强制的引用清除,防止内存泄漏
window.addEventListener('unload', function(event) {
console.log(event.target, '跳转了');
})
当页面大小发生改变时触发,可以用此来获取一些窗口属性,用来做响应式开发。但是大小改变检测很灵敏,所以需要做防抖
window.addEventListener('resize', function(event) {
console.log('大小改变');
console.log(window.innerWidth, window.innerHeight);
})
scrollLeft 和 scrollTop
这是存在于 document 上的两个属性,分别代表滚动条已经滚动的高度和宽度。他们与 clientWidth 、clienHeight一样都是页面视口的属性,并非整个浏览器创口属性。
该事件是在 window 对象上发生的,与 scrollTop,scrollLeft 有关。监听该事件可以用来做导航栏的变化,同样要做防抖,否则容易卡顿
window.addEventListener('scroll', function(event) {
console.log('滚动');
console.log(document.documentElement.scrollTop, document.documentElement.scrollLeft);
})
焦点一般只鼠标的焦点,虽然可以检测鼠标事件来监控,但是焦点可以通过键盘移动所以有专门的事件监控。焦点事件标准不一,但是 DOM3 统一了一个标准并且规定了它的发生顺序
当一个元素移动到另一个元素会依次触发以下事件;一般 blur 与 focus 常见
主要是点击、双击、光标移入、移出、暗下、放开的操作;
触发顺序:
一般可以用于轮播图或者自动播放,当鼠标移入将其停止,移出又自动播放
var doc = document.querySelector('input');
doc.addEventListener('mouseenter', function() {console.log('暂停')} )
doc.addEventListener('mouseout', function() {console.log('开始')} )
可用于获取该事件发送时鼠标属性,在任何元素上通过鼠标滚动即可触发。可以检测页面滚动是否来自鼠标。该事件冒泡。
上述事件在移动端上又有所不同
按下字符键时依次触发 keydown -> keypress -> keyup 按下非字符键时依次触发 keydown -> keyup
另外发生 keydown 和 keyup 时,也可以通过 event 对象获取相应的键值(ASCII码值)。keyCode
let doc = document.querySelector('input');
doc.addEventListener('keyup',function(event) {
console.log(event.keyCode);
})
触发条件
可以通过 event.data 获得键盘实际输入值而非 ASCII 码值
let doc = document.querySelector('input');
doc.addEventListener('textInput',function(event) {
console.log(event.data);
})
设备事件不是值页面内的事件,而是移动设备本身事件,比如翻转、是否走动。目前的草案中有四种类型事件
这一类事件是移动设备的事件核心
扫码关注腾讯云开发者
领取腾讯云代金券
Copyright © 2013 - 2025 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有
深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569
腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287
Copyright © 2013 - 2025 Tencent Cloud.
All Rights Reserved. 腾讯云 版权所有