JavaScript事件机制详解:焦点、冒泡、绑定与兼容处理
本文深入解析JavaScript中的事件机制,涵盖焦点获取与丢失、事件对象event的使用、事件冒泡与捕获原理,以及IE与标准浏览器的兼容处理方案。详细对比了onclick、attachEvent与addEventListener的区别,并提供了键盘事件、默认行为阻止及常见交互案例的实现方法。
焦点与事件对象基础
焦点是指元素接收用户输入的能力,但并非所有元素都能获得焦点。
为元素设置焦点主要有以下几种方式:
第一种是通过鼠标点击。
第二种是通过Tab键导航。
第三种是通过JavaScript代码控制。
以输入框提示文字为例进行说明。
onfocus事件在元素获取焦点时触发。
element.onfocus = function(){};
onblur事件在元素失去焦点时触发。
element.onblur = function(){};
使用obj.focus()方法可以为指定元素设置焦点。
使用obj.blur()方法可以取消指定元素的焦点。
使用obj.select()方法可以选择指定元素内的文本内容。
以方块跟随鼠标移动为例进行说明。
event是事件对象,用于存储与当前事件相关的所有信息。
当事件发生时,相关信息会临时保存在event对象中,供后续调用,类似于飞机的黑匣子。
event对象仅在事件处理函数内部调用时才有内容。
判断一个函数是否为事件处理函数,取决于它是否被事件调用,而非定义方式。
浏览器兼容性与事件对象获取
不同浏览器对event对象的处理存在兼容性问题。
element.onclick = fn1;
在IE和Chrome浏览器中,event是一个内置的全局对象,可以直接使用。
function fn1(){
alert(event);
}
在标准浏览器中,event对象通过事件处理函数的第一个参数传入。
function fn1(ev){
alert(ev);
}
兼容写法如下:
function fn1(ev){
var ev = ev || event;
}
clientX和clientY表示鼠标距离页面可视区的坐标距离。
事件流:冒泡与捕获
以仿select控件为例进行说明。
事件冒泡是指元素接收到事件后,将事件向上传播至父级,直至window对象。
事件捕获是指父元素先接收到事件,再传递给子元素。
注意:IE浏览器不支持事件捕获。在标准绑定中,需特别注意这一点。
事件绑定与解绑方法对比
事件绑定主要有两种实现方式。
第一种方式是直接赋值。
element.onclick = fn1;
注意:执行oDiv.onclick = fn1;后,
再执行oDiv.onclick = fn2;
此时fn2会覆盖fn1,导致fn1无法执行。
第二种方式是使用特定的绑定方法。
IE浏览器使用obj.attachEvent(事件名称,事件函数)。
该方法不支持事件捕获。
事件名称需要包含'on'前缀。
事件函数的执行顺序:标准浏览器为正序,非标准浏览器为倒序。
在该方法中,this指向window对象。
element.attachEvent(onclick,fn1);
标准浏览器使用obj.addEventListener(事件名称,事件函数,是否捕获)。
该方法支持事件捕获。
事件名称不需要包含'on'前缀。
事件的执行顺序为正序。
在该方法中,this指向触发该事件的对象。
element.addEventListener(click,fn1,false);
bind函数用于封装绑定逻辑。
function bind(obj,evname,fn){
if(obj.addEventListener){
obj.addEventListener(evname,fn,false);
}else{
obj.attachEvent('on' + evname,function(){
fn.call(obj);
});
}
}
事件取消绑定主要有两种方法。
第一种是直接赋值null。
element.onclick = null;
第二种是使用特定的解绑方法。
IE浏览器使用obj.detachEvent(事件名称,事件函数)。
document.detachEvent('onclick',fn1);
标准浏览器使用obj.removeEventListener(事件名称,事件函数,是否捕获)。
document.removeEventListener('click',fn1,false);
键盘事件与默认行为处理
键盘事件以留言本为例进行说明。
onkeydown事件在键盘按键按下时触发。
onkeyup事件在键盘按键抬起时触发。
event.keyCode返回数字类型的键盘键值。
ctrlKey、shiftKey、altKey为布尔值。
当事件触发时,如果shift、ctrl或alt键未按下,则返回false,否则返回true。
默认事件以自定义右键菜单和键盘控制div运动为例进行说明。
事件默认行为是指浏览器在事件发生时默认执行的操作。
阻止默认行为可以使用return false。
oncontextmenu事件在右键菜单显示时触发。
常见交互案例实现
具体案例如下:
方块跟随鼠标移动案例。
onmouseover事件在鼠标移入元素时触发。
注意:触发频率基于时间间隔而非像素距离,在固定间隔内无论鼠标移动多远只触发一次。
<style>
body{
height: 2000px;
}
#div{
width:100px;
height: 100px;
background:red;
position: absolute;
}
</style>
<body>
<div id="div1"></div>
</body>
<script>
var oDiv = document.getElementById('div1');
document.onmouseover = function(ev){
var ev = ev || event;
// 如果当滚动条滚动了(页面的头部部分隐藏了),方块是以页面定位的,而鼠标是以可视区定位的,这样就会产生bug。所以我们要加上滚动条滚动的距离
var scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
oDIv.style.top = ev.clientX + scrollTop + 'px';
oDIv.style.left = ev.clientY + 'px';
}
</script>
输入框文字提示案例。
<style></style>
<body>
<input type="text" id="text1" value="请输入内容"/>
<input type="button" id="btn" value="全选" />
</body>
<script>
var oText = document.getElementById('text1');
var oBtn = document.getElementById('btn');
oText.onfocus = function(){
if(this.value == '请输入内容'){
this.value = '';
}
}
oText.onblur = function(){
if(this.value == ''){
this.value = '请输入内容';
}
}
oBtn.onclick = function(){
oText.select();
}
</script>
仿select控件案例。
<style>
#div1{
width: 100px;
height: 200px;
border: 1px solid red;
display: none;
}
</style>
<body>
<input type="button" value="按钮" id="btn" />
<div id="div1"></div>
<p>ppppppppp</p>
<p>ppppppppp</p>
<p>ppppppppp</p>
<p>ppppppppp</p>
<p>ppppppppp</p>
</body>
<script>
window.onload = function(){
var oBtn = document.getElementById('btn');
var oDiv = document.getElementById('div1');
oBtn.onclick = function(ev){
var ev = ev || event;
ev.cancelBubble = true;
oDiv.style.display = 'block';
}
document.onclick = function(){
oDiv.style.display = 'none';
}
}
</script>
留言本案例。
<style></style>
<body>
<input type="text" id="con"/>
<ul id="box"></ul>
</body>
<script>
var oUl = document.getElementById('box');
var oText = document.getElementById('con');
document.onkeyup = function(ev){
var ev = ev || even;
if(ev.keyCode != ''){
if(ev.keyCode == 13){
var oLi = document.createElement('li');
oLi.innerHTML = oText.value;
if(oUl.children[0]){
oUl.insertBefore(oLi,oUl.children[0]);
}else{
oUl.appendChild(oLi);
}
}
}
}
</script>
自定义右键菜单案例。
<style>
body{
height: 2000px;
}
#box{
width: 100px;
height: 200px;
background: red;
display: none;
position: absolute;;
}
</style>
<body>
<div id="box"></div>
</body>
<script>
var oBox = document.getElementById('box');
document.oncontextmenu = function(ev){
var ev = ev || event;
var scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
var scrollLeft = document.documentElement.scrollLeft || document.body.scrollLeft;
oBox.style.display = 'block';
oBox.style.top = scrollTop + ev.clientY + 'px';
oBox.style.left = scrollLeft + ev.clientX + 'px';
return false;
}
document.onclick = function(){
oBox.style.display = 'none';
}
</script>
键盘控制div运动案例。
<style>
#box{
width: 100px;
height: 100px;
background: red;
position: absolute;
}
</style>
<body>
<div id="box"></div>
</body>
<script>
var oBox = document.getElementById('box');
var timer = null;
var oLeft = false;
var oTop = false;
var oRight = false;
var oBottom = false;
// 运动一直就绪,等待按键操作
timer = setInterval(function(){
if(oLeft){
oBox.style.left = oBox.offsetLeft - 10 + 'px';
}else if(oTop){
oBox.style.top = oBox.offsetTop - 10 + 'px';
}else if(oRight){
oBox.style.left = oBox.offsetLeft + 10 + 'px';
}else if(oBottom){
oBox.style.top = oBox.offsetTop + 10 + 'px';
}
// 防止溢出
limit();
},10);
// 按键按下,开始运动
document.onkeydown = function(ev){
var ev = ev || even;
switch (ev.keyCode){
case 37:
oLeft = true;
break;
case 38:
oTop = true;
break;
case 39:
oRight = true;
break;
case 40:
oBottom = true;
break;
}
}
// 按键抬起,停止运动
document.onkeyup = function(ev){
var ev = ev || even;
switch (ev.keyCode){
case 37:
oLeft = false;
break;
case 38:
oTop = false;
break;
case 39:
oRight = false;
break;
case 40:
oBottom = false;
break;
}
}
function limit(){
// 控制左边
if(oBox.offsetLeft <= 0){
oBox.style.left = 0;
}
// 控制上边
if(oBox.offsetTop <= 0){
oBox.style.top = 0;
}
// 控制右边
if(document.documentElement.clientWidth - oBox.offsetLeft - oBox.offsetWidth < 0){
oBox.style.left = document.documentElement.clientWidth - oBox.offsetWidth + 'px';
}
// 控制下边
if(document.documentElement.clientHeight - oBox.offsetTop - oBox.offsetHeight < 0){
oBox.style.top = document.documentElement.clientHeight - oBox.offsetHeight + 'px';
}
}
</script>
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持本站!
JS怎么实现页面强制刷新
2026-11-05 14:53:38
点击JS链接直接运行不下载?前端实现.js文件强制下载的三种方法
2026-11-05 12:12:23
怎么封装一个通用的JS创建元素辅助函数
2026-11-05 11:41:41
Swiper.js 怎么监听滑动结束并获取当前索引
2026-11-05 10:57:15
HTML、CSS和JS的关系:Web前端三件套怎么协作
2026-11-04 15:41:40
