事件触发后的回调函数,大家须要分成七个部分来产生这一个动作

在前端开发中,我们经常需要对某些事件进行监听。这样只要在指定的元素上触发了该事件,就会执行一个回调来进行相关的操作。

从零开始学习javascript项目(2)

而js中事件监听方法总共有三种,分别如下所示:

任务描述

  • 读取页面中id为source的列表,提取城市以及对应的空气质量
  • 把数据排序以后,在resort列表中按照顺序显示出来
<ul id="source">
    <li>北京空气质量:<b>90</b></li>
    <li>上海空气质量:<b>70</b></li>
    <li>天津空气质量:<b>80</b></li>
    <li>广州空气质量:<b>50</b></li>
    <li>深圳空气质量:<b>40</b></li>
    <li>福州空气质量:<b>32</b></li>
    <li>成都空气质量:<b>90</b></li>
  </ul>

  <ul id="resort">
    <!-- 
    <li>第一名:北京空气质量:<b>90</b></li>
    <li>第二名:北京空气质量:<b>90</b></li>
    <li>第三名:北京空气质量:<b>90</b></li>
     -->
  </ul>
  <button id="sort-btn">排序</button>
  • element.addEventListener(type, listener[, useCapture]); // IE6~8不支持
  • element.attachEvent(’on’ + type, listener); // IE6~10,IE11不支持
  • element[’on’ + type] = function(){} // 所有浏览器

任务规划

为了完成这个任务,我们需要分成三个部分来完成这个动作

  • 按下button的时候触发动作
  • 美高梅4688官方网站,抓取页面上的列表到一个数组里面
  • 把排序后的数组通过操作DOM使得新数组append到新的列表里面

demo:

绑定按钮动作与事件监听

和之前提到的一样,对于按钮这个事件的触发,需要一个监听函数。首先使用抓取按钮的DOM

var sort_btn = document.getElementById('sort-btn');

再对这个元素进行监听动作。

关于事件监听,详细点这里。如果不想看那么多,可以看下面的精简版。

简单的来说js的事件监听有三种方法

  • element.addEventListener(type, listener[, useCapture]); // IE6~8不支持
  • element.attachEvent(’on’ + type, listener); // IE6~10,IE11不支持
  • element[’on’ + type] = function(){} // 所有浏览器

举个栗子:

function cb() { console.log(1); }
element.addEventListener('click', cb, false);
element.attachEvent('onclick', cb);
element.onclick = cb;

type :事件类型

listener :事件触发后的回调函数

useCapture :是否使用捕获,如果值为true, useCapture 表示用户希望发起捕获。 在发起捕获之后, 只要Dom子树下发生了该事件类型,都会先被该事件监听器捕获,然后再被派发到Dom子树中的事件监听器中。并且向上冒泡的事件不会触发那些发起捕获的事件监听器。 useCapture 默认值为false

addEventListener是W3C工作组在DOM Level 2开始引入的一个注册事件监听器的方法;而在此之前,传统的事件监听方法是通过element[’on’ + type]的方式来注册的。它们两之间的主要区别是,element[’on’ + type]的方式无法使用事件捕获,并且element[’on’ + type]不支持对同一个元素的同一个事件注册多个事件监听器。如下面的例子所示,元素被点击后只会输出1,而不会输出0和1.

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

看完我的解释,是不是更加不明白了?没关系,赶紧点击这里。 回过头好好看一下好了。

function cb() { console.log(1); }
element.addEventListener('click', cb, false);
element.attachEvent('onclick', cb);
element.onclick = cb;

浅谈事件的捕获和冒泡

对于所有中国人来说,有一个四字魔咒是永远绕不开的。只要有人对你说出这四个字,你就能中邪般地买票去最坑爹的景点、玩命爬上最艰险的山峰、吃下最难吃的餐馆饭菜…这四个字就是———来都来了。

所以,既然看到这了,我就带你们去了解一点更深入的知识吧,毕竟来都来了

参数含义:

事件

javascript使用的是异步事件模型,如果你写过verilog,那么对这个概念应该会比较熟悉,而且javascript中的异步事件是基于触发器的,也就是说你不必考虑异步时钟域里面的数据传输而产生的亚稳态和计算数据传输的带宽。异步事件的在于只要使用时间处理函数注册一个回调函数,一旦事件触发,就会立刻执行回调函数。

type:事件类型

DOM事件流的阶段

所谓的事件流,就是事件在处理事件传播过程中的顺序,根据W3C模型的定义,这个传播过程分别是捕获阶段,目标阶段,冒泡阶段。事件阶段存在的意义子啊与 当我们在一个元素里面潜逃另外一个元素,并且这两者都绑定了一个onClink事件,就像下面这样

+-----------------+
|    event1       |
|  +-----------+  |
|  |  event2   |  |
|  +-----------+  |
|                 |
+-----------------+

(效果来自这里不是闲的蛋疼不要尝试,不过画点简单的东西还是很给力的)。当点击事件发生的时候,哪一个先被触发,执行的顺序是什么?W3C模型采用的是一种先捕获再冒泡的的方式,大概就像下面这样的。

                      / \
+----------------| |--| |----------------+
| element1       | |  | |                |
|   +------------| |--| |----------+     |
|   |element2    \ /  | |          |     |
|   +------------------------------+     |
|        W3C event model                 |
+----------------------------------------+

​ 我们以一个例子来说明这种流程

<div id = "s1"> s1
  <div id = "s2">s2</div>
</div>
<script>
    s1.addEventListener("click",function(evt){
      console.log("s1捕获模式");
    },true);
    s2.addEventListener("click",function(evt){
      console.log("s2捕获模式");
    },true);
    s1.addEventListener("click",function(evt){
      console.log("s1冒泡模式");
    },false);
    s2.addEventListener("click",function(evt){
      console.log("s2冒泡模式");
    },false);
</script>    

结果如下

s1捕获模式
s2捕获模式
s2冒泡模式
s1冒泡模式

我们可以通过这个例子看到,事件传播的过程根据addEventListener方法设置的第三个参数确定捕获的模式。在捕获阶段,事件到达事件目标之前,事件对象必须从windows经过目标的祖先节点传播到时间目标,在这个阶段注册的事件监听器在到达目标之前必须先处理事件。在目标阶段,事件对象到达事件目标,该阶段的事件监听器就会对其进行处理。最后就是冒泡阶段,事件对象以一个与捕获阶段相反的方向经过祖节点传播到window。在这个阶段注册的事件监听器会对相应的冒泡时间进行处理。

这样就很清楚了。我再贴一张官方图片:

美高梅4688官方网站 1

事件触发过程

如果你看不到上面的图片,那么高清无码大图在这里 。当然,我们也可以使用stopPropagation这个函数来停止事件的传播,这里就不展开了。如果你有兴趣的话,可以研究一下关于IE对于事件捕获的操作方法,通过监听父节点而不是监听父节点下面的每一个子节点来节约浏览器的资源,通过关闭冒泡和捕获使函数的执行互不干扰而节约浏览器的资源等等。

listener:事件触发后的回调函数

回归主线

好了,说了这么多。我们在自己的项目里面需要用到的大概就是这么一句话

var sort_btn = document.getElementById('sort-btn');
sort_btn.addEventListener('click',function(){btnHandle()},false);

useCapture:是否使用捕获,如果值为true, useCapture 表示用户希望发起捕获。 在发起捕获之后, 只要Dom子树下发生了该事件类型,都会先被该事件监听器捕获,然后再被派发到Dom子树中的事件监听器中。并且向上冒泡的事件不会触发那些发起捕获的事件监听器。进一步的解释可以查看 DOM Level 3 Events 文档。 useCapture 默认值为false 。

抓取列表元素到数组

这就是简单的操作DOM的内容了,我们的目标是把城市和数字存到一个个的键值对中。

//函数应该这么写
function getData(){
  var data = document.getElementById('source').getElementByTagName('li');
  var a = [];
  var city;
  var num;
  for(var i=0; i<data.length; i++){
    city = data[i].innerHTML.substring(0,data[i].innerHTML.indexOf('空'));
    num = data[i].getElementByTagName('b')[0].innerHTML;
    a.push([city,num]);
  }
  return a;
}
  • innerHTML不仅可以修改HTML元素还可以把元素内容返回出来。
  • substring用于提取字符串中介于两个指定下标之间的字符。其内容是从 start 处到 stop-1 处的所有字符
  • indexOf() 方法可返回某个指定的字符串值在字符串中首次出现的位置

addEventListener是W3C工作组在DOM Level 2开始引入的一个注册事件监听器的方法;而在此之前,传统的事件监听方法是通过element[’on’ + type]的方式来注册的。它们两之间的主要区别是,element[’on’ + type]的方式无法使用事件捕获,并且element[’on’ + type]不支持对同一个元素的同一个事件注册多个事件监听器。如下面的例子所示,元素被点击后只会输出1,而不会输出0和1.

对列表元素进行排序

这一部分也很简单,教科书一般的排序方式。

function sortAqiData(data){
    data.sort(function(a,b){
      return (a[1]-b[1]);
    }) 
}
element.onclick = function(){ console.log(0); }
element.onclick = function(){ console.log(1); }

通过操作DOM使排序后的数据显示出来

function render(data){
    var resort = document.getElementById('resort');
    resort.innerHTML = '';
    for(var i=0; i< data.length; i++){
      var node = document.creatElement('li');
      var html = '第'+(i+1)+'名:'+data[i][0]+'空气质量:<b>'+data[i][1]+'</b>';
      node.innerHTML = html;
      resort.appendChild(node);
    }
}

这样,一个简单的交互功能就算完成了。

然而addEventListener方法在IE6~8的浏览器中不被支持。那么在低版本的IE中怎么来为同一个事件注册多个事件监听器呢?原来IE从IE5.0系列开始就引入了attachEvent()方法来支持这一特性。但遗憾的是该方法也不支持事件捕获。并且从IE 11开始,这个方法已经被弃用。

谈谈事件的捕获和冒泡

美高梅4688官方网站 2

W3C规范中定义了3个事件阶段,依次是捕获阶段、目标阶段、冒泡阶段。事件对象按照上图的传播路径依次完成这些阶段。如果某个阶段不支持或事件对象的传播被终止,那么该阶段就会被跳过。举个例子,如果Event.bubbles属性被设置为false,那么冒泡阶段就会被跳过。如果Event.stopPropagation()在事件派发前被调用,那么所有的阶段都会被跳过。

  • 捕获 阶段:在事件对象到达事件目标之前,事件对象必须从window经过目标的祖先节点传播到事件目标。 这个阶段被我们称之为捕获阶段。在这个阶段注册的事件监听器在事件到达其目标前必须先处理事件。
  • 目标 阶段:事件对象到达其事件目标。 这个阶段被我们称为目标阶段。一旦事件对象到达事件目标,该阶段的事件监听器就要对它进行处理。如果一个事件对象类型被标志为不能冒泡。那么对应的事件对象在到达此阶段时就会终止传播。
  • 冒泡 阶段: 事件对象以一个与捕获阶段相反的方向从事件目标传播经过其祖先节点传播到window。这个阶段被称之为冒泡阶段。在此阶段注册的事件监听器会对相应的冒泡事件进行处理。

在一个事件完成了所有阶段的传播路径后,它的Event.currentTarget会被设置为null并且Event.eventPhase会被设为0。Event的所有其他属性都不会改变(包括指向事件目标的Event.target属性)

<script src="http://htmljs.b0.upaiyun.com//js/tuiku.js"></script>

本文由美高梅4688官方网站发布于最新话题,转载请注明出处:事件触发后的回调函数,大家须要分成七个部分来产生这一个动作

您可能还会对下面的文章感兴趣: