面试官:考你几个简单的事件问题吧
面试官:考你几个简单的事件问题吧。 几小时后的你:虽然面试官考的很简单,但是就是没有答上来。
事件处理是JavaScript中非常重要的概念,我们使用的客户端软件往往都是事件驱动的,所以面试官特别喜欢问一些事件相关的知识,这里记录几个常见的问题,供大家学习。
事件流的三个阶段:事件捕获阶段、目标阶段和事件冒泡阶段(这个问题大多数同学都知道,很容易被问懵)。
事件处理函数(事件侦听器):响应的某个事件函数。
添加事件有几种方式(以click事件为例)?
- 在HTML中添加
onclick
属性,值使用JS的字符串来表示要执行的事件。 <input type="button" id="btn" value="按钮" onclick="handleClick()"> <script type="text/javascript"> function handleClick(){ console.log("按钮被点击了"); } </script> - 给DOM元素添加
onclick
方法,如下 var btn = document.getElementById("btn"); btn.onclick = function (){ console.log("按钮被点击了"); }; - DOM元素使用
addEventListener
(IE使用attachEvent
)来添加方法,如下 var btn = document.getElementById("btn"); btn.addEventListener("click",function (){ console.log("按钮被点击了"); });
上述这种onclick和addEventListener两种添加事件的方式有什么不同?
-
onclick
是DOM0级事件处理方式,而addEventListener
是DOM2级事件处理方式,所以兼容性onclick
会更好一些(虽然现在addEventListener
也不会有什么问题)。 -
addEventListener
可以添加多个方法,而onclick
只能添加一个。 -
addEventListener
可以添加第三个参数,表示是捕获还是冒泡阶段调用,如果为true的时候表示捕获阶段调用,如果是false的话表示冒泡阶段调用,默认是冒泡阶段调用(undefined相当于是false)。 btn.addEventListener("click",function (){ console.log("按钮被点击了"); },true); document.body.addEventListener("click",function (){ console.log("body被点击了"); },true); // 点击按钮的时候会先打印"body被点击了" 后 打印 "按钮被点击了" // 因为第三个参数是true的时候表示捕获阶段调用 // 如果第三个参数都是false的时候 那么先打印 "按钮被点击了" 后打印 "body被点击了" // 如果一个是false一个是true那么先打印为true的 因为捕获阶段先于冒泡阶段 -
addEventListener
可以使用removeEventListener
来删除事件处理程序,而onclick
最多只有一个事件处理程序,所以只要btn.onclick = null;
就可以了。
addEventListener与attachEvent有什么不同?
-
addEventListener
适用于正常的W3C浏览器,而attachEvent
适用于IE浏览器(注:Edge都不支持这玩意)。 -
attachEvent
第一个参数,需要带”on”。比如添加click事件那么attachEvent的第一个参数是”onclick”。 -
addEventListener
中的this指向DOM元素,而attachEvent
中的this指向window。 -
attachEvent
只支持冒泡不支持捕获,所以也就没有第三个参数。 -
attachEvent
如果添加多个事件处理程序那么先执行后添加的后执行先添加的,这与addEventListener恰好相反(IE9和IE10修改了执行顺序和addEventListener一样了,先添加的先执行)。
如何获取事件对象event?
通常情况下事件处理程序的第一个参数就是event对象,如下:
btn.addEventListener("click",function (event){
// event 就是事件对象 通常的习惯 也可以命名为e
});
但是有一种情况下例外,就是IE的DOM0级事件onclick
的情况下,使用的是window.event
来获取(没错attachEvent
也是通过事件处理函数的第一个参数来获取):
btn.onclick = function (event){
event = event || window.event;// 兼容性处理
console.log(event);
}
如何来阻止默认行为?
普通浏览器使用event.preventDefault()
来阻止默认行为,IE使用event.retureValue = false;
(注意:并不是函数return一个false)来阻止:
btn.onclick = function (event){
event = event || window.event;// 兼容性处理
if(event.preventDefault){// 阻止默认行为
event.preventDefault();
} else {
event.retureValue = false;// IE
}
}
如何来阻止事件冒泡?
普通浏览器使用event.stopPropagation();
来阻止事件冒泡,IE使用event.cancelBubble = true;
:
btn.onclick = function (event){
event = event || window.event;// 兼容性处理
if(event.stopPropagation){// 阻止事件冒泡
event.stopPropagation();
} else {
event.cancelBubble = true;// IE
}
}
那些标签支持load事件?
body(或者window对象),img,script(IE9+),link(IE和Opera支持)。
点击一下鼠标前后会调用那些事件?
mousedown > mouseup > click。
双击鼠标前后会调用那些事件?
mousedown > mouseup > click > mousedown > mouseup > click > dbclick。
点击一下键盘前后会调用那些事件?
keydown > keypress > keyup(注意这里与click的区别)。
按下键盘一直不放前后会调用那些事件?
keydown > keypress > keydown > keypress …
移动端触摸一下屏幕前后会调用那些事件?
touchstart > touchend > mouseover > mousemove(触发一次) > mousedown > mouseup > click。
事件处理做过什么优化?
- 使用事件委托,如表格中删除某一行可以把事件添加到表格上而不是td标签,然后判断那一个元素出发的,然后对特定元素做处理,这样既可以减少事件监听的数量有可以不用关系新增元素的时间。
- 移除HTML的时候,先把绑定的事件删除。
如果用户在页面上填写了一些数据现在要关闭页签,我想在用户关闭的时候提醒他一下该怎么做?
监听window
对象上的beforeunload
事件就可以了,可以设置event.returnValue
的值等于一个提示语,也有浏览器是根据返回的字符串来提示的:
function addEvent(element,type,handler){//通用事件添加函数
if (element.addEventListener) {
element.addEventListener(type,handler);
} else if (element.attachEvent) {
element.attachEvent("on" + type,handler);
} else {
element["on" + type] = handler;
}
}
addEvent(window,"beforeunload",function (event){
event = event || window.event;
var msg = "官人,你先别走啊,你填的东西还没有保存呢!请不要弃我而去啊...";
event.returnValue = msg;// IE的处理
return msg;//普通浏览器的处理
});
这里需要注意一点虽然我们给了特定的字符串并不是所有浏览器都会显示这个字符串的,Chrome就会给定特定的提示语而不是使用我们给定的字符串,但是只有给定字符串不为空(隐式转化为true)它才会给出提示。
下列代码依次打印的是什么?
// 这里btn还是上面的button元素。
btn.addEventListener("click",function (){
console.log("冒泡事件1")
},false);
btn.addEventListener("click",function (){
console.log("冒泡事件2")
},false);
document.body.addEventListener("click",function (){
console.log("document.body冒泡事件")
},false);
btn.addEventListener("click",function (){
console.log("捕获事件1")
},true);
btn.addEventListener("click",function (){
console.log("捕获事件2")
},true);
document.body.addEventListener("click",function (){
console.log("document.body捕获事件")
},true);
执行的结果是:
document.body捕获事件 冒泡事件1 冒泡事件2 捕获事件1 捕获事件2 document.body冒泡事件
事件是先捕获后冒泡的,所以第一个和最后一个是没有问题的。中间4个事件的执行,都是处于目标阶段,目标阶段会按照事件的添加顺序来执行,而不会管你是否是捕获还是冒泡。
如何让一个事件先冒泡后捕获?
浏览器都是先捕获后冒泡的(如果支持捕获的时候),并不支持先冒泡后捕获,我们可以改造一下捕获的函数,让他在冒泡结束后再执行,就可以达到类似的效果。如上面最后一个document.body
的事件可以像下面这样改造一下,那么document.body捕获事件
将会在最后打印。
document.body.addEventListener("click",function (){
setTimeout(() => {
console.log("document.body捕获事件")
}, 0);
},true);
- Vue + Node + Mongodb 开发一个完整博客流程
- Golang中用interface{}接收任何参数与强转
- Machine Box创始人教你快速建立一个ML图像分类器
- 【图解】Web前端实现类似Excel的电子表格
- 一个简单而强大的深度学习库—PyTorch
- CSS实现水平|垂直居中漫谈
- 深度学习开源框架PaddlePaddle发布新版API,简化深度学习编程
- HTML5游戏引擎深度测评
- 使用NumPy介绍期望值,方差和协方差
- Cleaver快速制作网页PPT
- 【学术】马尔可夫链的详细介绍及其工作原理
- 想把自拍背景改成马尔代夫?手把手教你用深度学习分分钟做到
- 还记得谷歌之前发现的两颗行星吗?今天谷歌对此披露了重要技术细节
- Golang调用动态库so
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- PHP大文件切割上传功能实例分析
- laravel Task Scheduling(任务调度)在windows下的使用详解
- PHP 7.4中使用预加载的方法详解
- PHP设计模式之工厂模式(Factory)入门与应用详解
- Laravel 实现Controller向blade前台模板赋值的四种方式小结
- Referer原理与图片防盗链实现方法详解
- Laravel 简单实现Ajax滚动加载示例
- PHP设计模式之解释器(Interpreter)模式入门与应用详解
- Laravel 实现在Blade模版中使用全局变量代替路径的例子
- PHP实现关键字搜索后描红功能示例
- 如何在CentOS中安装PHP7.4的方法步骤
- Linux安装Python3如何和系统自带的Python2并存
- Python Tricks 使用 pywinrm 远程控制 Windows 主机的方法
- PHP学习记录之常用的魔术常量详解
- laravel orm 关联条件查询代码