zepto 事件分析2($.on)

这里主要分析zepto事件中的$.on函数,先看一下该函数的代码

$.fn.on = function(event, selector, data, callback, one){
    var autoRemove, delegator, $this = this
    if (event && !isString(event)) {
      //多个事件下的处理
      $.each(event, function(type, fn){
        $this.on(type, selector, data, fn, one)
      })
      return $this
    }
    //根据传入的参数初始化各个参数
    //(event,data,callback)
    if (!isString(selector) && !isFunction(callback) && callback !== false)
      callback = data, data = selector, selector = undefined
    //(event,selector,callback)
    if (callback === undefined || data === false)
      callback = data, data = undefined
    //callback = function(){return false}
    if (callback === false) callback = returnFalse
    //迭代zepto对象中的元素
    return $this.each(function(_, element){
      if (one) autoRemove = function(e){
        remove(element, e.type, callback)
        return callback.apply(this, arguments)
      }
      //如果有传入选择器 定义一个delegator函数
      if (selector) delegator = function(e){
        //从触发事件目标出发找寻符合selector选择器的元素
        var evt, match = $(e.target).closest(selector, element).get(0)
        //如果存在并且不是element
        if (match && match !== element) {
          //对event对象进行转化操作
          evt = $.extend(createProxy(e), {currentTarget: match, liveFired: element})
          return (autoRemove || callback).apply(match, [evt].concat(slice.call(arguments, 1)))
        }
      }
      add(element, event, callback, data, selector, delegator || autoRemove)
    })
  }

该函数主要分析的是return 后面的语句,在前面的分析中,分析了each函数和$对象,也就是对$对象中的每一个dom进行绑定事件,这里先跳过autoRemove函数,留在后面分析,如果有传入选择器,zepto先定义一个delegator函数,delegator函数中有一个match变量,该变量即为我们要绑定事件的目标元素,zepto采用的是事件委托,官方文档对于closest的定义如下:

而e.target即是事件触发的元素,注意:currentTarget和e.target是不同的。target在事件流的目标阶段;currentTarget在事件流的捕获,目标及冒泡阶段。

<body>
<div class="out">
    <div class="in"><h2>1`</h2></div>
</div>
</html>
<script type="text/javascript">

function test2(e){
    console.log(e.target);
    console.log(e.currentTarget)
};
var box2 = document.getElementsByClassName(‘in‘)[0];
box2.addEventListener("click",test2);

当我们点击h2时,target指向<h2>,currentTarget指向<div class=‘in‘>;

在获得match之后,判断其是否存在或是否为元素本身,如果是,则什么都不做,如果不是,则创建一个新的事件evt,并将原来的事件属性赋值给evt,并改变currentTarget和 liveFired的属性值。

其中有一个createProxy函数,该函数的功能即为复制属性。

function createProxy(event) {
    var key, proxy = { originalEvent: event }
    for (key in event)
      if (!ignoreProperties.test(key) && event[key] !== undefined) proxy[key] = event[key]

    return compatible(proxy, event)
  }

createProxy函数最后返回的是一个compatible函数的执行,在之前分析$.Event就有遇到过,在这里来分析其作用。

function compatible(event, source) {    //如果没有传入source函数并且evnet事件阻止了默认操作,则直接返回传入的event参数
    if (source || !event.isDefaultPrevented) {
      source || (source = event)

      $.each(eventMethods, function(name, predicate) {
        var sourceMethod = source[name]
        event[name] = function(){
          this[predicate] = returnTrue
          return sourceMethod && sourceMethod.apply(source, arguments)
        }
        event[predicate] = returnFalse
      })

      event.timeStamp || (event.timeStamp = Date.now())
      //对其默认操作进行相关判断
      if (source.defaultPrevented !== undefined ? source.defaultPrevented :
          ‘returnValue‘ in source ? source.returnValue === false :
          source.getPreventDefault && source.getPreventDefault())
        event.isDefaultPrevented = returnTrue
    }
    return event
  }

该函数最主要的代码在中间的$.each(...),可以先看一下eventMethods的定义

eventMethods = {
        preventDefault: ‘isDefaultPrevented‘,
        stopImmediatePropagation: ‘isImmediatePropagationStopped‘,
        stopPropagation: ‘isPropagationStopped‘
      }

在原生的事件属性中,也存在prereventDefault等方法以及判断其值的defaultPrevented属性,但在zepto中,每次绑定事件,实际上都相当于重新定义一个事件,而自我定义的属性是不具备prereventDefault等方法的功能,那么defaultPrevented的值也就失效了。如图:

function test2(e){
    var evt = {};
    for(key in evt)
        evt[key] = e[key];
    evt.preventDefault();
};
var box2 = document.getElementsByClassName(‘in‘)[0];
box2.addEventListener("click",test2);

所以compatible函数的作用就是为了使原生事件preventDefault等的方法以及判断其值的属性转变为一个方法来使用。

delegator函数中,最后返回的是对绑定函数的执行。

最后on方法执行了一个add()函数,该函数留在下一篇分析。

时间: 2024-10-10 17:26:40

zepto 事件分析2($.on)的相关文章

zepto 事件分析1($.Event)

先看一下zepto事件的函数,在这里,zepto是把zepto对象作为一个立即执行函数的参数传进去的. (function($){ ... ... })(Zepto) 在zepto事件函数中,主要为$.Event,$.on,$.off等,分析事件代码,分析这三个就够了,首先分析$.Event函数,在分析该函数之前,从接口文档中大概知道这是一个创建事件的方法,可以先看一下原生的javascript代码是怎么生成一个事件的. var event = new Event('event'); //老式创

跨浏览器resize事件分析

resize事件 原生事件分析 window一次resize事件: IE7 触发3次, IE8 触发2次, IE9 触发1次, IE10 触发1次 Chrome 触发1次 FF 触发2次 Opera 触发1次 Safari 触发1次 场景分析 window resize时,部分组件需要重置大小(一次):部分组件不需要重置大小: 开源库分析 jquery-resize 优点:使用简便 $('#div1').on('resize', function (e) { console.log('[div1

Android中Preference的使用以及监听事件分析

> 在Android系统源码中,绝大多数应用程序的UI布局采用了Preference的布局结构,而不是我们平时在模拟器中构建应用程序时使用的View布局结构,例如,Setting模块中布局.当然,凡事都有例外,FMRadio应用程序中则使用了View布局结构(可能是该应用程序是marvel公司提供的,如果由google公司做,那可说不准).归根到底,Preference布局结构和View的布局结构本质上还是大同小异,Preference的优点在于布局界面的可控性和高效率以及可存储值的简洁性(每个

某游戏公司后台数据库SQL注入事件分析

某游戏公司后台数据库SQL注入事件分析 人物关系简介 Blank –SA Dawn(Boss) Ryan –DBA Fred –离开公司的安全顾问 本案例出自于<Unix/Linux网络日志分析与流量监控>一书,该事例详细描述了一家公司的后台服务器被入侵,黑客从中获取了大量游戏币帐号,并发送邮件相威胁的案例.主要遇到的问题是服务器被SQL注入或受到了SQL注入攻击 Blank是XX公司的网络架构师,技术好人缘也不错,他实际的工作室XX公司的"首席救火队员",每件事他都要自己

DuiLib事件分析(一)——鼠标事件响应

最近在处理DuiLib中自定义列表行元素事件,因为处理方案得不到较好的效果,于是只好一层一层的去剥离DuiLib事件是怎么来的,看能否在某一层截取消息,自己重写. 我这里使用CListContainerElementUI行元素,元素中有插入button,平时行元素不显示,鼠标移动上去显示出来,鼠标移走就隐藏button.Duilib自己是不带这个功能的,它有一个鼠标移动上去的热点事件,按理说重写热点事件就好了.但是当时比较急没找到怎么触发的,之后一直没继续走这条思路.后来找到源码事件里面有 vo

【Android 1.6】View和ViewGroup的touch事件分析和总结

ENV: android 1.6 目前Android版本已经到了7.0(nougat)了,Android 随着版本升级,touch事件的源码也在跟随着系统的升级而写得越来越复杂,加入了很多旁枝末节,这些旁枝末节,对于分析流程是一种干扰:由于Android的版本升级是向下兼容的,万变不离其宗,研究Android早期的版本,可以更容易理解touch事件的分发,本篇以Android1.6版本的源码进行讲解,由简及繁,理解了早期的源码,再进入高版本的研究也会更容易许多. 前言: View事件的派发其实非

Zepto源代码分析之二~三个API

因为时间关系:本次仅仅对这三个API($.camelCase.$.contains.$.each)方法进行分析 第一个方法变量转驼峰:$.camelCase('hello-world-welcome'); 源代码: var camelize; /** * 字符串替换 * 使用replace第二个參数带回调 */ camelize = function(str) { return str.replace(/-+(.)?/g, function(match, chr) { return chr ?

【转载+整理】Android中TouchEvent事件分析

原文地址:http://mobile.51cto.com/abased-374715.htm 一.知识回顾 一个最简单的屏幕触摸动作触发了一系列Touch事件:ACTION_DOWN->ACTION_MOVE->ACTION_MOVE->ACTION_MOVE...->ACTION_MOVE->ACTION_UP 二.问题提出 当屏幕中包含一个ViewGroup,而这个ViewGroup又包含一个子view,这个时候android系统如何处理Touch事件呢?到底是 View

Javascript冒泡事件分析

在javascript的dom操作做肯定会遇到js的冒泡事件,最常见的是div弹窗事件如图解 当点击灰色部分是弹窗消失,点击黑色部分时没有效果. 通过下面一段代码来分析js的冒泡事件 html代码: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>js冒泡事件</title> <link rel=&