首页 > 代码库 > day15

day15

## 总结:事件的捕捉和冒泡

### 1. 事件绑定###
**1.1 JavaScript脚本中绑定事件**
```
html:
<input type="button" id="btn" value="http://www.mamicode.com/点我"/>
JavaScript:
var btn = document.getElementById("btn");
方式1:
btn.onclick = function() {}
方式2:
function test() {
    console.log(123);
}
btn.onclick = test;
```
**1.2 标签中绑定事件**
```
<input type="button" id="btn" value="http://www.mamicode.com/点我" onclick="test()"/>
```
**1.3 监听器**
<table style=‘width:800px;font-size:14px;text-align:center;‘><tr><th>IE</th><th>CHROM,FIREFOX</th></tr><tr><td>element.attachEvent(event, function);//添加
        element.detachEvent(event, function);//删除</td><td>element.addEventListener(event, function, useCapture);//添加
            element.removeEventListener(event, function, useCapture);//删除</td></tr></table>

### 2. 事件对象###
**2.1 什么是事件源对象**

事件源对象是指event对象,其封装了与事件相关的详细信息.
- 当事件发生时,只能在事件函数内部访问的对象
- 处理函数结束后会自动销毁

**2.2 获取EVENT对象**
<table style="width:800px;font-size:14px;text-align:center;"> <tr><th></th><th>IE</th><th>w3c</th></tr><tr><td>事件源对象</td><td>window.event</td><td>e</td></tr></table>

**2.3 EVENT对象的属性**

**2.3.1 鼠标事件**
- 相对于浏览器位置
event.clientX: 返回当事件被触发时鼠标指针向对于浏览器页面(或客户区)的水平坐标
event.clientY: 返回当事件被触发时鼠标指针向对于浏览器页面(客户区)的垂直坐标

- 相对于屏幕位置
event.screenX: 返回事件发生时鼠标指针相对于屏幕的水平坐标
event.screenY: 返回事件发生时鼠标指针相对于屏幕的垂直坐标

- 相对于事件源位置
event.offsetX: 返回事件发生时鼠标指针相对于事件源的水平坐标
event.offsetY: 返回事件发生时鼠标指针相对于事件源的垂直坐标
event.layerX: 返回事件发生时鼠标指针相对于事件源的水平坐标(FIREFOX)
event.layerY: 返回事件发生时鼠标指针相对于事件源的垂直坐标(FIREFOX)

**2.3.2 键盘事件**
- keyCode:  获取按下的键盘按键的值的字符代码
- altKey: 指示在指定的事件发生时,Alt 键是否被按下
- ctrlKey: 指示当事件发生时,Ctrl 键是否被按下
- shiftKey: 指示当事件发生时,"SHIFT" 键是否被按下

**2.3.3 type属性**
用来检测事件类型

### 3 事件流###
当页面元素触发事件的时候, 该元素的容器以及整个页面都会按照特定的顺序响应该元素的触发事件,事件传播的顺序叫做事件流.


**3.1 事件流的分类**
- **冒泡型事件(Event Bubbling)**
所有浏览器都支持,由明确的事件源到最不确定的事件源依次向上触发.

- **捕获型事件(Event Capturing)** <br>
(IE不支持) 不确定的事件源到明确的事件源依次向下触发.
![](images/event.jpg)  
```
element.addEventListener(event, function, true);//捕获型
element.addEventListener(event, function, false);//冒泡型
```

- **DOM标准的事件模型**<br>我们已经对上面两个不同的事件模型进行了解释和对比。DOM标准同时支持两种事件模型,即捕获型事件与冒泡型事件,但是,捕获型事件先发生。两种事件流都会触发DOM中的所有对象,从document对象开始,也在document对象结束(大部分兼容标准的浏览器会继续将事件是捕捉/冒泡延续到window对象)。<br>
![](images/img03.png)

**3.2 阻止事件流**
IE: event.cancelBubble = true;
FF: event.stopPropagation();
**3.3 目标事件源**
IE: srcElement
FF: target

**3.3 js代码实例**

```JavaScript
(function() {
  var div1 = document.getElementById(‘box1‘);
  var div2 = document.getElementById(‘box2‘);
  var div3 = document.getElementById(‘box3‘);
  var input = document.getElementById(‘input‘);


  // 传统事件
  div1.onclick = function() {
    console.log(1);
  };
  div2.onclick = function() {
    console.log(2);
  };
  div3.onclick = function() {
    console.log(3);
  };

  function fn() {
    console.log(‘hello‘);
  }

  // 现代事件
  div3.addEventListener(‘click‘, fn, false);

  /**
   * 传统事件和现代事件的区别
   * 1. 传统事件只能给一个事件绑定一个事件处理函数,而现代事件可以给一个事件绑定多个事件处理函数
   * 2. 传统事件所有的浏览器都支持,现代事件在低版本的ie浏览器下不支持
   * 3. 现代事件既可以绑定在冒泡阶段,也可以绑定在捕获阶段;传统事件只能绑定在冒泡阶段
   */

  div3.onclick = function() {
    console.log(1);
  };

  div3.onclick = function() {
    console.log(2);
  };
  div3.addEventListener(‘click‘, function() {
    alert(1);
  }, false);
  div3.addEventListener(‘click‘, fn, false);
  div3.removeEventListener(‘click‘, fn, false);


  // 对于最里层的节点来说,捕获阶段和冒泡阶段的事件,哪个一事件先绑定,就会先执行哪一个事件

  div2.addEventListener(‘click‘, function() {
    console.log(5);
  }, false);
  div1.addEventListener(‘click‘, function() {
    console.log(4);
  }, false);
  div1.addEventListener(‘click‘, function() {
    console.log(1);
  }, true);
  div2.addEventListener(‘click‘, function() {
    console.log(2);
  }, true);
  div3.addEventListener(‘click‘, function() {
    console.log(3);
  }, true);
  div3.addEventListener(‘click‘, function() {
    console.log(6);
  }, false);

  div3.attachEvent(‘onclick‘, function() {
    alert(1);
  });
  div3.attachEvent(‘onclick‘, function() {
    alert(2);
  });

  div1.addEventListener(‘click‘, function() {
    console.log(1);
  }, true);
  div2.addEventListener(‘click‘, function() {
    console.log(2);
  }, true);
  div3.addEventListener(‘click‘, function() {
    console.log(3);
  }, true);

  div1.onclick = function() {
    console.log(1);
  };
  div2.onclick = function() {
    console.log(2);
  };
  div3.onclick = function(event) {
    // console.log(a);
    // console.log(a.offsetX, a.offsetY);
    // console.log(a.screenX, a.screenY);
    // console.log(a.clientX, a.clientY);
    console.log(3);
    // stopPropagation 阻止事件继续传播
    event.stopPropagation();
  };

  // 在点击div3之后,浏览器执行
  // 浏览器先创建事件对象,用于保存和事件相关的信息
  var event = {
  ...
  };
  div.onclick(event);

  input.onkeydown = function(event) {
    // console.log(event);
    if(event.keyCode >= 48 && event.keyCode <= 57) {
      console.log(‘hello, number‘);
    }
  };

  input.onkeydown = function(e) {
    // console.log(e.keyCode);
    if(e.keyCode === 67 && e.altKey === true) {
      alert(‘触发快捷键‘);
    }
  };

  div1.addEventListener(‘click‘, function() {
    console.log(1);
  }, true);
  div2.addEventListener(‘click‘, function() {
    console.log(2);
  }, true);
  div3.addEventListener(‘click‘, function(event) {
    event.stopPropagation();
    console.log(3);
  }, true);
  div1.addEventListener(‘click‘, function() {
    console.log(4);
  }, false);
  div2.addEventListener(‘click‘, function() {
    console.log(5);
  }, false);
  div3.addEventListener(‘click‘, function(event) {
    console.log(6);
  }, false);

  var event = {
    a: 10,
    b: 20
  };

  var obj = {};   // true
  var arr = [];   // true

  div1.onclick = function() {
    alert(1);
  };
  div2.onclick = function() {
    alert(2);
  };
  div3.onclick = function(event) {
    // 系统申明形参
    // 在标准浏览器下 var event = 事件对象;
    // 在ie浏览器下 var event = undefined;
    alert(event);

    event.stopPropagation();
    event.cancelBubble = true;

    if(event === undefined) {
      event = window.event;
    }
    event = event || window.event;
    // 兼容两个浏览器
    if(event.stopPropagation) {
      event.stopPropagation();
    } else {
      event.cancelBubble = true;
    }
    alert(3);
  };


  event.preventDefault();
  阻止事件的默认行为
  在传统事件中,还可以使用return false的方式来阻止事件的默认行为
  input.onkeydown = function(event) {
    // event.preventDefault();
    console.log(‘hello‘);
    return false;
  };

  input.addEventListener(‘keydown‘, function(event) {
    console.log(‘hello‘);
    // event.preventDefault();
    return false;
  }, false);
})();

```

 

day15