DOM事件

一、事件

跟用户交互时,dom结构发不发生改变,此时就用到事件了。
事件是当用户对浏览器进行点击某个地方都可能触发任何一个事件,如用户鼠标单击时、 鼠标移动到元素上。

二、事件流

1.事件冒泡模型

事件开始时由最具体的元素接收,然后逐级向上传播到较为不具体的元素,也就是说
从里向外

.jpg

2.事件捕获模型

从外向里

3.DOM事件流模型

先捕获,在冒泡

三、使用方式

DOM0

事件处理程序
也称事件侦听器,当用户或浏览器自身执行了某个事件,而响应某个事件就叫事件处理程序

1.js指定事件

<input id="btnClick" type="button" value="Click Here" />

<script type="text/javascript">
    var btnClick = document.getElementById('btnClick');
    btnClick.onclick = function showMessage() {//元素.事件=事件处理函数 ()    //onclick也可是其他事件名称
        alert(this.id);
    };
</script>
 //如果是多个相同事件注册用这种方式,最后一个执行,之前的被覆盖了

(2)对一个元素绑定多个事件函数 (注:会发生覆盖)

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>JS Bin</title>
</head>
<body>
  <button id="btn">click me</button>
</body>
</html>
<script>
var btn = document.querySelector('#btn')
//#事件01
btn.onclick = function(){
console.log(this)
console.log(this.innerText)
}
//#事件02
 btn.onclick = function(){
  console.log('hello world')
}
</script>
事件01被覆盖
DOM2事件处理程序

DOM2级事件定义了两个方法用于处理指定和删除事件处理程序的操作:

  • addEventListener
  • removeEventListener
    所有的DOM节点都包含这两个方法,并且它们都接受三个参数
    1.事件类型
    2.事件处理方法
    3.布尔参数,如果是true表示在捕获阶段调用事件处理程序,如果是false,则是在事件冒泡阶段处理
绑定事件

addEventListener

为同一个元素绑定多个相同的事件:

绑定事件的两个属性:
- 对象.addEventListener("事件类型",事件处理函数,false);--谷歌和火狐支持,IE8不支持
- 对象.attachEvent("有on的事件类型(如:onclick)",事件处理函数)--谷歌不支持,火狐不支持,IE8支持


<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>title</title>
</head>
<body>
<input type="button" value="按钮" id="btn"/>
</body>
<script>
如:
第一种:
//为按钮绑定点击事件
  //参数1:事件的类型----事件的名字,没有on
  //参数2:事件处理函数----函数(命名函数,匿名函数)
  //参数3:布尔类型----默认是事件冒泡(false),事件捕获(true)
function btn$(id) {
    return document.getElementById(id);
}
 btn$("btn").addEventListener("click",function () {
   console.log("呵呵");
 },false);//默认是false,可写可不写
 btn$("btn").addEventListener("click",function () {
   console.log("哈哈");
 },false);
 btn$("btn").addEventListener("click",function () {
   console.log("哦哦");
 },false);
 btn$("btn").addEventListener("click",function () {
   console.log("谔谔");
 },false);

第二种:
//参数1:事件类型---事件名字,有on
//参数2:事件处理函数---函数(命名函数,匿名函数)
function btn$(id) {
    return document.getElementById(id);
}
btn$("btn").attachEvent("onclick",function () {
  console.log("谔谔");
 });
 btn$("btn").attachEvent("onclick",function () { 
 console.log("哦哦");
 });
btn$("btn").attachEvent("onclick",function () {
   console.log("哈哈");
 });
//JavaScript指定事件的事件是:onclick,DOM2事件处理程序的事件是:click
</script>

没有发生覆盖


没有发生覆盖
总结:总结绑定事件的区别:
  • addEventListener();
  • attachEvent()
  • 相同点: 都可以为元素绑定事件
  • 不同点:
  • 1.方法名不一样
  • 2.参数个数不一样addEventListener三个参数,attachEvent两个参数
  • 3.addEventListener 谷歌,火狐,IE11支持,IE8不支持
  • attachEvent 谷歌火狐不支持,IE11不支持,IE8支持
  • 4.this不同,addEventListener 中的this是当前绑定事件的对象
  • attachEvent中的this是window
  • 5.addEventListener中事件的类型(事件的名字)没有on
  • attachEvent中的事件的类型(事件的名字)有on
为按钮绑定多个点击事件
function btn$(id) {
    return document.getElementById(id);
}
  btn$("btn").addEventListener("click",function () {
  console.log(this);
  },false);
  btn$("btn").attachEvent("onclick",function () {
   console.log(this);
 });
如何解绑事件(一般情况下不做)

removeEventListener
removeEventListener不能使用匿名函数(无法获知要移除谁)
如:

<script type="text/javascript">
    var btnClick = document.getElementById('btnClick');
    var handler=function() {
        alert(this.id);
    }
    btnClick.removeEventListener('click', handler, false);
</script>

四、演示

冒泡阶段与阻止冒泡
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>title</title>
  <style>
    #dv1{
      width: 300px;
      height: 200px;
     border: 1px solid ;
    }
    #dv2{
      width: 250px;
      height: 150px;
     border: 1px solid ;
    }
    #dv3{
      width: 200px;
      height: 100px;
      border: 1px solid ;
    }
  </style>
</head>
<body>
<div id="dv1">a
  <div id="dv2">b
    <div id="dv3">c</div>
  </div>
</div>
<script>
function $(id) {
    return document.getElementById(id);
}
  //事件冒泡-->阻止事件冒泡,
  //如何阻止事件冒泡: window.event.cancelBubble=true; IE特有的,谷歌支持,火狐不支持
//.preventDefault()    //取消时间默认行为。
  // .stopPropagation(); 谷歌和火狐支持。   //描述:取消事件进一步捕获或冒泡

  $("dv1").onclick=function () {
    console.log(this.id);
  };
 $("dv2").onclick=function () {
    console.log(this.id);
    //window.event.cancelBubble=true; //阻止事件冒泡 
  };

  //事件处理参数对象
  $("dv3").onclick=function (e) {  //加参数e
    console.log(this.id);   
   e.stopPropagation();  //阻止事件冒泡   //参数e
    console.log();
  };
</script>
</body>
</html>
从里到外
  • 事件冒泡:多个元素嵌套,有层次关系,这些元素都注册了相同的事件,如果里面的元素的事件触发了,外面的元素的该事件自动的触发了.
    整个事件就是从里到外
捕获阶段
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>title</title>
  <style>
    #dv1 {
      width: 300px;
      height: 200px;
      border: 1px solid ;
    }
    #dv2 {
      width: 250px;
      height: 150px;
      border: 1px solid ;
    }
    #dv3 {
      width: 200px;
      height: 100px;
      border: 1px solid ;
    }
  </style>
</head>
<body>
<div id="dv1">a
  <div id="dv2">b
    <div id="dv3">c</div>
  </div>
</div>
<script>
function btn$(id) {
    return document.getElementById(id);
}
  //捕获阶段:是从里向外

  //同时注册点击事件
  var objs = [btn$("dv3"),btn$("dv2"), btn$("dv1")];
  //遍历注册事件
  objs.forEach(function (ele) {
    //为每个元素绑定事件
    ele.addEventListener("click", function () {
      console.log(this.id);
    }, true);//捕获阶段是true,冒泡阶段是false
  });
  //该属性在事件参数对象中存在
</script>
</body>
</html>
从里向外
事件有三个阶段:
 * (Dom2传播机制)三个阶段:
 * 1.事件捕获阶段  :从外向内
 * 2.事件目标阶段  :最开始选择的那个
 * 3.事件冒泡阶段  : 从里向外
 *
 * 为元素绑定事件:
 * addEventListener("没有on的事件类型",事件处理函数,控制事件阶段的)
 * 事件触发的过程中,可能会出现事件冒泡的效果,为了阻止事件冒泡--->
 * window.event.cancelBubble=true;谷歌,IE8支持,火狐不支持
 * window.event就是一个对象,是IE中的标准
 * e.stopPropagation();阻止事件冒泡---->谷歌和火狐支持
 * window.event和e都是事件参数对象,一个是IE的标准,一个是火狐的标准
 * 事件参数e在IE8的浏览器中是不存在,此时用window.event来代替
 * addEventListener中第三个参数是控制事件阶段的
 * 事件的阶段有三个:
 * 通过e.eventPhase这个属性可以知道当前的事件是什么阶段的
 * 如果这个属性的值是:
 * 1---->捕获阶段
 * 2---->目标阶段
 * 3---->冒泡
 * 一般默认都是冒泡阶段,很少用捕获阶段
 * 冒泡阶段:从里向外
 * 捕获阶段:从外向内

区别:
onlick与addEventListener的区别?
1.onclick事件在同一时间只能指向唯一对象
2.addEventListener给一个事件注册多个listener
3.addEventListener对任何DOM都是有效的,而onclick仅限于HTML
4.addEventListener可以控制listener的触发阶段,(捕获/冒泡)。对于多个相同的事件处理器,不会重复触发,不需要手动使用removeEventListener清除
5.IE9使用attachEvent和detachEvent

attachEvent与addEventListener的区别
参数个数不相同:

  • addEventListener有三个参数,attachEvent只有两个,attachEvent添加的事件处理程序只能发生在冒泡阶段,addEventListener第三个参数可以决定添加的事件处理程序是在捕获阶段还是冒泡阶段处理(默认冒泡)

  • 第一个参数意义不同:
    addEventListener第一个参数是事件类型(比如click,load),而attachEvent第一个参数指明的是事件处理函数名称(onclick,onload)

  • 事件处理程序的作用域不相同:
    addEventListener的作用域是元素本身,this是指的触发元素;而attachEvent事件处理程序会在全局变量内运行,this是window,所以刚才例子才会返回undefined,而不是元素id

  • 为一个事件添加多个事件处理程序时执行顺序不同:
    addEventListener添加会按照添加顺序执行,而attachEvent添加多个事件处理程序时顺序无规律(添加的方法少的时候大多是按添加顺序的反顺序执行的,但是添加的多了就无规律了),所以添加多个的时候,不依赖执行顺序的还好,若是依赖于函数执行顺序,最好自己处理,不要指望浏览器。

自定义事件

var EventCenter = {
  on: function(type, handler){
    document.addEventListener(type, handler)
  },
  fire: function(type, data){
    return document.dispatchEvent(new CustomEvent(type, {
      detail: data
    }))
  }
}

EventCenter.on('hello', function(e){
  console.log(e.detail)
})

EventCenter.fire('hello', '你好')
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,904评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,581评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,527评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,463评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,546评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,572评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,582评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,330评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,776评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,087评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,257评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,923评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,571评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,192评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,436评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,145评论 2 366
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,127评论 2 352

推荐阅读更多精彩内容

  • dom对象的innerText和innerHTML有什么区别? innerHTML指的是从对象的起始位置到终止位置...
    coolheadedY阅读 487评论 0 0
  • 事件流 JavaScript与HTML之间的交互是通过事件实现的。事件,就是文档或浏览器窗口中发生的一些特定的交互...
    DHFE阅读 827评论 0 3
  • 一、问答 1. dom对象的innerText和innerHTML有什么区别? innerHTML: 也就是从对象...
    饥人谷_罗伟恩阅读 596评论 0 2
  • 问答 一、dom对象的innerText和innerHTML有什么区别? innerTextinnerText是一...
    婷楼沐熙阅读 403评论 0 0
  • 题目1: DOM0 事件和DOM2级在事件监听使用方式上有什么区别? Dom0级Dom0级事件处理程序是将一个函数...
    QQQQQCY阅读 317评论 0 0