面试题 event 事件

  • 事件委托是什么?
  • 如何阻止事件冒泡,阻止默认事件呢?
  • Javascript 的事件流模型都有什么?
  • 事件绑定和普通事件有什么区别?

Event 对象

Event 对象,当事件发生的时候出发某个函数,该 Event 对象将自动在函数内可用,该对象包含了很多事件触发时候的信息,

但 IE 却没有这么实现,而是自己实现的,IE 浏览器是通过全局对象 window 下的 event 属性来包含这些信息

function myEventHandler(e) {
// 注意参数e
// 该函数调用的时候e是event对象(W3C实现)
// 兼容IE的代码
e = e || window.event;
// 现在e就可以兼容各种浏览器了
}

事件注册

这里最重要的就是 IE 的 attachEvent 和 W3C 标准 addEventListener 在执行上的一些区别

  1. attachEvent 只支持事件冒泡 addEventListener 既支持事件冒泡,也支持事件捕获
  2. 参数:attachEvent 事件类型需要 on 前缀 addEventListener 事件类型不需要 on 前缀
  3. 如果使用 attachEvent 对一个元素的目标阶段绑定了多次事件,那么会按照绑定顺序的相反顺序进行触发。如果使用 addEventListener 对一个元素的目标阶段绑定了多次事件,那么会按照绑定顺序进行触发

w3c

var oBtn = document.getElementById("btn1");
oBtn.addEventListener('click', introClick, false);

ie

var oBtn = document.getElementById("btn1");
oBtn.attachEvent('onclick', introClick);

兼容写法

      var oBtn = document.getElementById("btn1");
addEvent(oBtn, "click", show);
addEvent(oBtn, "click", show2);
// removeEvent(oBtn, "click", show); //对象.addEventListener(事件名,函数,false); for 高
//事件名 onclick over/out/down/up.........不带on
//函数 obj.onclick=show show==函数
function addEvent(obj, eve, fn) {
if (obj.addEventListener) {
obj.addEventListener(eve, fn, false); //由于事件参数不带on
} else {
obj.attachEvent("on" + eve, fn); //所以这里的绑定事件要将on补上
}
} //解绑
//对象.removeEventListener(事件名,函数,false); chrome FF IE 9 10
//对象.detachEvent(事件名,函数); IE 6 7 8
// oBtn.detachEvent('onclick',show2);
//移除函数
function removeEvent(obj, eve, fn) {
if (obj.removeEventListener) {
obj.removeEventListener(eve, fn, false);
} else {
obj.detachEvent("on" + eve, fn);
}
} function show() {
alert("我将弹出1");
} function show2() {
alert("我将弹出2");
}

删除匿名函数的引用

addEvent(oBtn, 'click', function(){
alert("弹出1");
//arguments对象包含了所有传递进来的参数以及该函数自身(callee)
console.log(arguments);
removeEvent(oBtn, 'click', arguments.callee);
});

W3C 和微软模型还有其他的少许差异,callee 是返回正在被执行的 function 函数,也就是所指定的 function 对象的正文。arguments.callee 知道就好了,别在代码中用了

事件冒泡和捕获

当年,IE 是冒泡流,而网景是捕获流,W3C 费些力使 JS 支持了冒泡流和捕获流。但是前些年或者更之前的时候,IE 还是老大,于是早期的 IE 浏览器并不支持捕获。

冒泡

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>事件冒泡</title>
<style></style>
<script>
window.onload = function() {
_id("div1").addEventListener(
"click",
function() {
alert(_id("div1").style.background);
},
false
); _id("div2").addEventListener(
"click",
function() {
alert(_id("div2").style.background);
},
false
); _id("div3").addEventListener(
"click",
function() {
alert(_id("div3").style.background);
},
false
); function _id(id) {
return document.getElementById(id);
}
};
</script>
</head> <body>
<div id="div1" style="width:500px; height:500px; background:red;">
<div id="div2" style="height:300px; width:300px; background:yellow">
<div id="div3" style="width:100px; height:100px; background:blue"></div>
</div>
</div>
</body>
</html>

捕获

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>事件捕获</title>
<style></style>
<script>
window.onload = function() {
var oDiv1 = document.getElementById("div1");
var oDiv2 = document.getElementById("div2");
var oDiv3 = document.getElementById("div3"); oDiv1.addEventListener(
"click",
function() {
alert(oDiv1.style.background);
},
true
); oDiv2.addEventListener(
"click",
function() {
alert(oDiv2.style.background);
},
true
); oDiv3.addEventListener(
"click",
function() {
alert(oDiv3.style.background);
},
true
);
};
</script>
</head> <body>
<div id="div1" style="width:500px; height:500px; background:red;">
<div id="div2" style="height:300px; width:300px; background:yellow">
<div id="div3" style="width:100px; height:100px; background:blue"></div>
</div>
</div>
</body>
</html>

addEventListener 的第三个参数 true 就是捕获,false 就是冒泡

阻止默认行为

    <script type="text/javascript">
var oBtn = document.getElementById("btn1");
addEvent(oBtn, "click", myEventHandler); //对象.addEventListener(事件名,函数,false); for 高
//事件名 onclick over/out/down/up.........不带on
//函数 obj.onclick=show show==函数
function addEvent(obj, eve, fn) {
if (obj.addEventListener) {
obj.addEventListener(eve, fn, false); //由于事件参数不带on
} else {
obj.attachEvent("on" + eve, fn); //所以这里的绑定事件要将on补上
}
} function myEventHandler(e) {
e = e || window.event;
// 防止默认行为
if (e.preventDefault) {
e.preventDefault();
} else {
e.returnValue = false;
}
}
</script>

禁止一下鼠标右键

    document.getElementById("contextmenu").addEventListener(
"contextmenu",
function(ev) {
var oEvt = ev || event;
oEvt.preventDefault(); //阻止默认
},
false
);

阻止冒泡

<script>
window.onload = function() {
_id("div1").addEventListener(
"click",
function() {
alert(_id("div1").style.background);
},
false
); _id("div2").addEventListener(
"click",
function() {
alert(_id("div2").style.background);
},
false
); _id("div3").addEventListener("click", myParagraphEventHandler, false); function _id(id) {
return document.getElementById(id);
} function myParagraphEventHandler(e) {
alert(this.style.background);
e = e || window.event;
// 停止向上冒泡
if (e.stopPropagation) {
// W3C实现
e.stopPropagation();
} else {
// IE实现
e.cancelBubble = true;
}
}
};
</script>

为什么我们要阻止默认事件呢?

  1. 异步操作
  2. 提交表单之前对表单进行一些基本的验证,比如邮箱是否合法,用户名是不是满足指定的格式,为了不让 a 点击之后跳转,我们就要给他的点击事件进行阻止
  3. 文本框获得焦点

事件委托

事件委托描述的是将事件绑定在容器元素上,然后通过判断点击的 target 子元素的类型来触发相应的事件

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Title</title>
</head>
<body>
<table id="my-table">
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>4</td>
<td>5</td>
<td>6</td>
</tr>
<tr>
<td>7</td>
<td>8</td>
<td>9</td>
</tr>
<tr>
<td>11</td>
<td>22</td>
<td>33</td>
</tr>
<tr>
<td>44</td>
<td>55</td>
<td>66</td>
</tr>
</table>
</body>
<script>
var myTable = document.getElementById("my-table"); myTable.onclick = function(e) {
// 处理浏览器兼容
e = e || window.event;
var targetNode = e.target || e.srcElement; if (targetNode.nodeName.toLowerCase() === "td") {
alert("You clicked a table row!");
}
};
</script>
</html>

DOM 事件流

这就是为什么捕获事件中,目标阶段是最后。而在冒泡事件中,目标阶段是最先了

面试题答案

  • 利用事件冒泡的原理,让自己的所触发的事件,让他的父元素代替执行 2.阻止冒泡 ie 是 ;其他是;

  • 浏览器 阻止冒泡 阻止默认
    ie ev.cancelBubble = true return false
    其他 ev.stopPropagation() ev.preventDefault()
  • "事件冒泡":事件开始由最具体的元素接受,然后逐级向上传播

    "事件捕捉":事件由最不具体的节点先接收,然后逐级向下,一直到最具体的

    "DOM 事件流":三个阶段:事件捕捉,目标阶段,事件冒泡

  • xxx.onEvent = function(){}其实是赋值操作,下面取缔上面的。而事件绑定可以一口气绑定多个事件,按绑定顺序执行

xxx.onEvent 就是对监听属性赋值一个函数,取消绑定设置为空就好了 xxx.onEvent = null

常见事件

鼠标事件

  • mousedown 鼠标设备按下一个元素的时候触发 mousedown 事件
  • mouseup 鼠标设备从按下的元素上弹起的时候触发 mouseup 事件
  • click 鼠标点击元素的时候触发 click 事件
  • dblclick 鼠标双击元素的时候触发 dblclick 事件
  • mouseover 鼠标移动到某元素上的时候触发 mouseover 事件
  • mouseout 鼠标从某元素离开的时候触发 mouseout 事件
  • mousemove 鼠标在某元素上移动但未离开的时候触发 mousemove 事件

键盘事件

  • keypress 按键按下的时候触发该事件
  • keydown 按键按下的时候触发该事件,并且在 keypress 事件之前
  • keyup 按键松开的时候触发该事件,在 keydown 和 keypress 事件之后

表单事件

  • select 文本字段(input, textarea 等)的文本被选择的时候触发该事件
  • change 控件失去 input 焦点的时候触发该事件(或者值被改变的时候)
  • submit 表单提交的时候触发该事件
  • reset 表单重置的时候触发该事件
  • focus 元素获得焦点的时候触发该事件,通常来自鼠标设备或 Tab 导航
  • blur 元素失去焦点的时候触发该事件,通常来自鼠标设备或 Tab 导航

其它事件

  • load 页面加载完毕(包括内容、图片、frame、object)的时候触发该事件
  • resize 页面大小改变的时候触发该事件(例如浏览器缩放)
  • scroll 页面滚动的时候触发该事件
  • unload 从页面或 frame 删除所有内容的时候触发该事件(例如离开一个页面)

参考

MDN - addEventListener

JavaScript 权威指南(第 5 版)

[JavaScript] JavaScript事件注册,事件委托,冒泡,捕获,事件流的更多相关文章

  1. jquery easyui控件事件监听委托给jquery事件监听,keyup取最新值问题

    <div id="<?php echo NS; ?>toolbar"> <div style="padding:5px"> ...

  2. AngularJs 阻止事件运行,防止冒泡穿透事件

    ng-click 低啊用方法后 添加语句$event.stopPropagation(); <button type="button" ng-click="doSo ...

  3. javascript --- 事件冒泡与事件捕获

    事件冒泡与事件捕获 事件冒泡和事件捕获分别由微软和网景公司提出,这两个概念都是为了解决页面中事件流(事件发生顺序)的问题.考虑下面这段代码,就不写html->head,body之类的代码了,自行 ...

  4. js之事件冒泡和事件捕获及其阻止详细介绍

    虽然精通jquery,但对它的原型javascript却不是很了解,最近在学习javascript中遇到了一些困难,比如冒泡和捕获,很多次被提到,但又不知究竟应用在何处.找到了一些好文章解惑,在这里分 ...

  5. quick-cocos2d-x游戏开发【10】——触摸捕获事件 cc.NODE_TOUCH_CAPTURE_EVENT

    假设看过sample中touch的代码,你会发现演示样例中有一个cc.NODE_TOUCH_CAPTURE_EVENT事件.它和cc.NODE_TOUCH_EVENT触摸事件一样,是引擎级别的事件,我 ...

  6. javaScript事件机制深入学习(事件冒泡,事件捕获,事件绑定方式,移除事件方式,阻止浏览器默认行为,事件委托,模拟浏览器事件,自定义事件)

    前言 JavaScript与HTML之间的交互是通过事件实现的.事件,就是文档或浏览器窗口中发生的一些特定的交互瞬间.可以使用侦听器(或处理程序)来预订事件,以便事件发生时执行相应的代码.这种在传统软 ...

  7. 【JavaScript】事件捕获、事件冒泡与事件委托

    2018年12月18日 最近在学习js时,遇到了三个名词:事件捕获.事件冒泡.事件委托. 一.事件捕获和事件冒泡 事件捕获和事件冒泡是为了解决网页中的事件流(事件发生的顺序)而提出的概念. 事件捕获是 ...

  8. javascript的事件冒泡,阻止事件冒泡和事件委托, 事件委托是事件冒泡的一个应用。

    首先,弄明白js 当中,什么是事件,事件模型在js中是如何设计的.什么是事件冒泡? 什么是“事件冒泡”呢?假设这里有一杯水,水被用某种神奇的方式分成不同颜色的几层.这时,从最底层冒出了一个气泡,气泡会 ...

  9. javascript中的事件冒泡、事件捕获和事件执行顺序

    谈起JavaScript的 事件,事件冒泡.事件捕获.阻止默认事件这三个话题,无论是面试还是在平时的工作中,都很难避免. DOM事件标准定义了两种事件流,这两种事件流有着显著的不同并且可能对你的应用有 ...

随机推荐

  1. Vue中scoped css和css module比较

    scoped css 官方文档 scoped css可以直接在能跑起来的vue项目中使用. 使用方法: <style scoped> h1 { color: #f00; } </st ...

  2. Web开发者の实用代码账簿

    介里就都是恶魔菌整理的我平时会用的代码啦-现在在这里总结规划一下,希望能对你以及其他阅读这篇文章的小可耐们有帮助喵!欢迎订阅我的博客来get恶魔菌记事簿的新动态鸭! ↓ ↓ ↓ 以下就是内容啦~记得看 ...

  3. 33 ArcToolBox学习系列之数据管理工具箱——投影与变换(Projections and Transformations)未完待续……

    工具箱位置 打开ArcToolBox,找到工具集Projections and Transformations,位置如下:ArcToolbox--Data Management Tools--Proj ...

  4. 如何安装并且使用jmeter进行简单的性能测试

    Jmeter  介绍 Jmeter  是一款使用Java开发的,开源免费的,测试工具, 主要用来做功能测试和性能测试(压力测试/负载测试). 而且用Jmeter 来测试 Restful API, 非常 ...

  5. C语言面试题分类->字符串处理

    1.strlen:计算字符串长度(不包含'\0') 实现想法:遍历字符串,直到'\0'结束 #include<stdio.h> #include<stdlib.h> #incl ...

  6. Java作业七(2017-10-30)

    /*造人*/ public class Tman { public int id; public String name; public int age; public String city; pu ...

  7. kali linux 网络渗透测试学习笔记(一)Nmap工具进行端口扫描

    一.利用Nmap扫描网站服务器的端口开放情况 首先打开我们的kali linux才做系统,再打开其命令行模式,输入:nmap www.csdn.net 如下图所示: 因此,通过这个结果可以表明csdn ...

  8. Apache Storm 核心概念

    前言: Storm读取实时数据流,并传递给处理单元,最终输出处理后的数据. 下图描述了storm的处理数据的主要结构. 元组(Tuple) :       元组是Storm提供的一个轻量级的数据格式, ...

  9. [Swift]LeetCode272. 最近的二分搜索树的值 II $ Closest Binary Search Tree Value II

    Given a non-empty binary search tree and a target value, find k values in the BST that are closest t ...

  10. [Swift]LeetCode551. 学生出勤纪录 I | Student Attendance Record I

    You are given a string representing an attendance record for a student. The record only contains the ...