资讯专栏INFORMATION COLUMN

JS事件模型

mylxsw / 216人阅读

摘要:事件模型事件模型共有两个过程事件处理阶段。事件绑定监听函数的方式如下事件移除监听函数的方式如下参数说明指定事件类型注意加是事件处理函数级模型属于标准模型,现代浏览器除之外的浏览器都支持该模型。

JS事件模型 观察者模式

观察者模式又叫做发布订阅者模式(Publish/Subscribe),它可以让多个观察者对象同时监听某一个主题对象,这个主题对象的状态变化时会通知所有的订阅者,使得它们能够做出反应。
JS的事件模型就是一种观察者模式的体现,当对应的事件被触发时,监听该事件的所有监听函数都会被调用。

下面是用JS实现的一个观察者模式的代码:

var events = (function() {
  var topics = {};

  return {
    publish: function(topic, info) {
      console.log("publish a topic:" + topic);
      if (topics.hasOwnProperty(topic)) {
        topics[topic].forEach(function(handler) {
          handler(info ? info : {});
        })
      }
    },
    subscribe: function(topic, handler) {
      console.log("subscribe an topic:" + topic);
      if (!topics.hasOwnProperty(topic)) {
        topics[topic] = [];
      }

      topics[topic].push(handler);
    },
    remove: function(topic, handler) {
      if (!topics.hasOwnProperty(topic)) {
        return;
      }

      var handlerIndex = -1;
      topics[topic].forEach(function(element, index) {
        if (element === handler) {
          handlerIndex = index;
        }
      });

      if (handlerIndex >= 0) {
        topics[topic].splice(handlerIndex, 1);
      }
    },
    removeAll: function(topic) {
      console.log("remove all the handler on the topic:" + topic);
      if (topics.hasOwnProperty(topic)) {
        topics[topic].length = 0;
      }
    }
  }
})();

使用事例:

//主题监听函数
var handler = function(info) {
    console.log(info);
}
//订阅hello主题
events.subscribe("hello", handler);

//发布hello主题
events.publish("hello", "hello world");
事件与事件流

事件是与浏览器或文档交互的瞬间,如点击按钮,填写表格等,它是JS与HTML之间交互的桥梁。
DOM是树形结构,如果同时给父子节点都绑定事件时,当触发子节点的时候,这两个事件的发生顺序如何决定?这就涉及到事件流的概念,它描述的是页面中接受事件的顺序。

事件流有两种:

事件冒泡(Event Capturing): 是一种从下往上的传播方式。事件最开始由最具体的元素(文档中嵌套层次最深的那个节点接受, 也就是DOM最低层的子节点), 然后逐渐向上传播到最不具体的那个节点,也就是DOM中最高层的父节点。

事件捕获(Event Bubbling): 与事件冒泡相反。事件最开始由不太具体的节点最早接受事件, 而最具体的节点最后接受事件。

事件模型 DOM0级模型

又称为原始事件模型,在该模型中,事件不会传播,即没有事件流的概念。事件绑定监听函数比较简单, 有两种方式:

HTML代码中直接绑定:

通过JS代码指定属性值:

var btn = document.getElementById(".btn");
btn.onclick = fun;

移除监听函数:

  btn.onclick = null;

这种方式所有浏览器都兼容,但是逻辑与显示并没有分离。

IE事件模型

IE事件模型共有两个过程:

事件处理阶段(target phase)。事件到达目标元素, 触发目标元素的监听函数。

事件冒泡阶段(bubbling phase)。事件从目标元素冒泡到document, 依次检查经过的节点是否绑定了事件监听函数,如果有则执行。

事件绑定监听函数的方式如下:

attachEvent(eventType, handler)

事件移除监听函数的方式如下:

detachEvent(eventType, handler)

参数说明:

eventType指定事件类型(注意加on)

handler是事件处理函数

Example:

var btn = document.getElementById(".btn");
btn.attachEvent(‘onclick’, showMessage);
btn.detachEvent(‘onclick’, showMessage);
DOM2级模型

属于W3C标准模型,现代浏览器(除IE6-8之外的浏览器)都支持该模型。在该事件模型中,一次事件共有三个过程:

事件捕获阶段(capturing phase)。事件从document一直向下传播到目标元素, 依次检查经过的节点是否绑定了事件监听函数,如果有则执行。

事件处理阶段(target phase)。事件到达目标元素, 触发目标元素的监听函数。

事件冒泡阶段(bubbling phase)。事件从目标元素冒泡到document, 依次检查经过的节点是否绑定了事件监听函数,如果有则执行。

事件绑定监听函数的方式如下:

addEventListener(eventType, handler, useCapture)

事件移除监听函数的方式如下:

removeEventListener(eventType, handler, useCapture)

Example:

var btn = document.getElementById(".btn");
btn.addEventListener(‘click’, showMessage, false);
btn.removeEventListener(‘click’, showMessage, false);

参数说明:

eventType指定事件类型(不要加on)

handler是事件处理函数

useCapture是一个boolean用于指定是否在捕获阶段进行处理,一般设置为false与IE浏览器保持一致。

事件对象

当一个事件被触发时,会创建一个事件对象(Event Object), 这个对象里面包含了与该事件相关的属性或者方法。该对象会作为第一个参数传递给监听函数。

DOM事件模型中的事件对象常用属性:

type用于获取事件类型

target获取事件目标

stopPropagation()阻止事件冒泡

preventDefault()阻止事件默认行为

IE事件模型中的事件对象常用属性:

type用于获取事件类型

srcElement获取事件目标

cancelBubble阻止事件冒泡

returnValue阻止事件默认行为

Event Wrapper

由于事件模型的差异以及Event对象的不同,为了达到兼容各个浏览器的目的,我们可以增加一个Event Wrapper, 它对各个浏览器应当提供一致的事件操作接口。

var eventUtils={
     // 添加句柄
     addHandler:function(element,type,handler){
       if(element.addEventListener){
         element.addEventListener(type,handler,false);
       }else if(element.attachEvent){
         element.attachEvent("on"+type,handler);
       }else{
         element["on"+type]=handler;
       }
     },
     // 删除句柄
     removeHandler:function(element,type,handler){
       if(element.removeEventListener){
         element.removeEventListener(type,handler,false);
       }else if(element.detachEvent){
         element.detachEvent("on"+type,handler);
       }else{
         element["on"+type]=null;
       }
     },
    //获取事件对象
    //IE模型中event是一个全局唯一的对象绑定在window对象上
    getEvent:function(event){
       return event?event:window.event;
    },
    //获取类型
    getType:function(event){
     return event.type;
    },
    getElement:function(event){
     return event.target || event.srcElement;
    },
    //阻止默认事件
    preventDefault:function(event){
     if(event.preventDefault){
      event.preventDefault();
     }else{
      event.returnValue=false;
     }
    },
    //阻止冒泡
   stopPropagation:function(event){
   if(event.stopPropagation){
     event.stopPropagation();
   }else{
     event.cancelBubble=true;
    }
   }
  }

参考:

DOM事件揭秘

事件代理

事件在冒泡过程中会上传到父节点,因此可以把子节点的监听函数定义在父节点上,由父节点的监听函数统一处理多个子元素的事件,这种方式称为事件代理(Event delegation)。

我们有一个div元素,它包含三个按钮:

我们可以在父节点上一次性的为所有子节点注册监听函数:

var box = document.getElementById("box");

box.addEventListener("click", function(event) {
  if (event.target.tagName.toLowerCase() === "input") {
    // some code
  }
});
自定义事件

JS中已经内置了很多事件,如click, mouseover等等,但是内置事件毕竟有限,有时候我们想自己定义一些事件,例如三连击,threeclick。如何实现自定义事件呢?

首先要创建一个事件。可以使用以下方式:

var event = new Event("threeclick", {"bubbles":true, "cancelable":false});

然后我们需要为事件注册监听函数:

target.addEventListener("threeclick", hello, false);

最后我们要在合适的时机触发该事件,我们可以使用dispatchEvent函数。该方法在当前节点触发指定事件,从而触发监听函数执行。该方法返回一个布尔值,只要有一个监听函数调用了Event.preventDefault(), 则返回false, 否则返回true。

target.dispatchEvent(event);
JQuery Event模型

JQuery解决的一个主要问题就是浏览器的兼容问题,它有自己的事件模型实现方式。它主要有以下特性:

重定义了JQuery.Event对象, 统一了事件属性和方法, 统一了事件模型

可以在一个事件类型上添加多个事件处理函数, 可以一次添加多个事件类型的事件处理函数

支持自定义事件(事件命名空间)

提供了toggle, hover组合事件

提供了one, live-die, delegate-undelegate

提供了统一的事件封装, 绑定, 执行, 销毁机制

$(document).ready();

....

JQuery事件具体代码请参考: https://github.com/jquery/jqu...
JQuery事件具体使用方式请自行查找

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/80388.html

相关文章

  • Backbone.js学习笔记(一)

    摘要:它通过数据模型进行键值绑定及事件处理,通过模型集合器提供一套丰富的用于枚举功能,通过视图来进行事件处理及与现有的通过接口进行交互。 本人兼职前端付费技术顾问,如需帮助请加本人微信hawx1993或QQ345823102,非诚勿扰 1.为初学前端而不知道怎么做项目的你指导 2.指导并扎实你的JavaScript基础 3.帮你准备面试并提供相关指导性意见 4.为你的前端之路提供极具建设性的...

    FrancisSoung 评论0 收藏0
  • 详解JS事件 - 事件模型/事件流/事件代理/事件对象/自定义事件

    摘要:取消事件的默认行为。阻止事件的派发包括了捕获和冒泡阻止同一个事件的其他监听函数被调用。 事件模型 DOM0 级事件模型 -没有事件流,这种方式兼容所有浏览器 // 方式一 将事件直接通过属性绑定在元素上 / 方式二 获取到页面元素后,通过 onclick 等事件,将触发的方法指定为元素的事件 var btn = document.getElementById(btn) btn....

    URLOS 评论0 收藏0
  • [面试专题]JS事件模型

    摘要:在这个事件发生期间,调用可阻止滚动当手指从屏幕上移开时触发。关于此事件的确切触发事件,文档中没有明确说明。特定于事件目标的对象的数组。 JS事件模型 事件模型以及周边 事件捕获 事件冒泡 事件触发 移动端事件模拟 事件委托 事件流 事件捕获(event capturing)&事件冒泡(event bubbling) 给inner,out均绑定点击事件.点击inne...

    lindroid 评论0 收藏0
  • [gist]为什么事件驱动服务器这么火

    摘要:两个事件驱动模型服务器平均每秒处理的请求数为服务器的一倍,而内存降低了一半。事件驱动模型的出现,是为了解决传统服务器与网络工作负载的需求的不匹配,实现高度可伸缩服务器,并降低内存开销。 from http://oyanglul.us 本文基本上这为两篇文章的翻译和整合 -...

    fsmStudy 评论0 收藏0
  • javascript -- 事件--事件流-- 冒泡 --捕获

    摘要:在内联模型中,事件处理函数是标签的一个属性,用于处理指定事件。事件捕获与冒泡原理图事件流同时支持两种事件模型捕获型事件和冒泡型事件,但是,捕获型事件先发生。 javascript -- 事件 事件是js和用户操作交互的桥梁, JavaScript 有三种事件模型:内联模型、脚本模型和 DOM2 模型 内联模型 这种模型是最传统接单的一种处理事件的方法。在内联模型中,事件处理函数是 HT...

    leeon 评论0 收藏0

发表评论

0条评论

mylxsw

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<