非常适合新手的jq/zepto源码分析06 -- 事件模型

复习下事件的有关内容:

1.现在用的绑定/删除:

  obj.addEventListener(type,fn,false)

  obj.removeEventListener(type)

  obj.attachEvent(type,fn)   //ie

  obj.detachEvent(type)

2.js的event对象

  type : 事件类型

  srcElement/target :  事件源

  button : 如果是鼠标按下,则 1左键 2右键 4中间滚轮 多个键则相加按下的所有值。 firfox 0左键1右键2滚轮

  clientX/clientY : 鼠标相当于文档的位置

  offsetX/offsetY/layerX/layerY : 鼠标相对于源元素位置

  altKey/ctrKey/shiftkey : alt / ctr / shift 是否按下

  keyCode : 键盘事件的 返回键的对应值

  relateTarget : {fromElement/toElement} 鼠标进入离开时候的相关元素

  cancelBubble/stopPropagtion() : 阻止冒泡事件

  screenX/screenY : 相对于显示器的位置

  returnValue/preventDefault() :  阻止元素默认事件

差不多就这么多,在不行就去百度搜文档。

 $.event = { add: add, remove: remove }

  

直接绑定在对象上面了

     function add(element, events, fn, data, selector, delegator, capture){       //element:绑定的元素       //events:事件,空格隔开       //fn:函数        //data : 向事件上绑定数据       //selector : 选择器       //delegator : 回调,用于事件委托       //capture : 冒泡
            var id = zid(element), set = (handlers[id] || (handlers[id] = []))
            events.split(/\s/).forEach(function(event){
                if (event == ‘ready‘) return $(document).ready(fn)         //parse(e) 解析事件 例如  click.cname   -->{e:click,ns:cname}
                var handler   = parse(event)
                handler.fn    = fn
                handler.sel   = selector
                // emulate mouseenter, mouseleave
                if (handler.e in hover) fn = function(e){            //移入移除绑定 给事件绑定相关元素
                    var related = e.relatedTarget
                    if (!related || (related !== this && !$.contains(this, related)))
                        return handler.fn.apply(this, arguments)
                }
                handler.del   = delegator
                var callback  = delegator || fn
                handler.proxy = function(e){            //处理event事件
                    e = compatible(e)            //是否阻止剩下的事件
                    if (e.isImmediatePropagationStopped()) return
                    e.data = data            //执行函回调函数
                    var result = callback.apply(element, e._args == undefined ? [e] : [e].concat(e._args))
                    if (result === false) e.preventDefault(), e.stopPropagation()
                    return result
                }
                handler.i = set.length
                set.push(handler)
                if (‘addEventListener‘ in element)            //绑定事件
                    element.addEventListener(realEvent(handler.e), handler.proxy, eventCapture(handler, capture))
            })
        }

  

_zid   :   每一个绑定事件的元素都有一个唯一ID
handlers :  所有的事件回调句柄都会以 ID 为键值保存在 handles里面,handles[_zid] = [handle1,handle2,...]

headler :  { fn : 函数,del : 回调, i : index位置 , sel : css选择器 , e : 当前事件名称 , proxy :代理函数(执行的函数)  }
  function remove(element, events, fn, selector, capture){       //对应的事件ID
            var id = zid(element)
                ;(events || ‘‘).split(/\s/).forEach(function(event){         //findHandlers 找到要移除的句柄 返回一个数组
                findHandlers(element, event, fn, selector).forEach(function(handler){            //移除句柄
                    delete handlers[id][handler.i]
                    if (‘removeEventListener‘ in element)              //接触绑定的该函数
                        element.removeEventListener(realEvent(handler.e), handler.proxy, eventCapture(handler, capture))
                })
            })
        }

  

  $.proxy = function(fn, context) {
            var args = (2 in arguments) && slice.call(arguments, 2)
            if (isFunction(fn)) {          //fn如果是函数  就相当于proxyFn fn.apply(conteng,args)  proxyFn 加了个位置ID
                var proxyFn = function(){ return fn.apply(context, args ? args.concat(slice.call(arguments)) : arguments) }
                proxyFn._zid = zid(fn)
                return proxyFn
            } else if (isString(context)) {          
                if (args) {
                    args.unshift(fn[context], fn)            
                    return $.proxy.apply(null, args)
                } else {
                    return $.proxy(fn[context], fn)
                }
            } else {
                throw new TypeError("expected function")
            }
        }

  

        $.fn.on = function(event, selector, data, callback, one){
            var autoRemove, delegator, $this = this        //event是数组或者类数组
            if (event && !isString(event)) {
                $.each(event, function(type, fn){            //迭代执行该函数
                    $this.on(type, selector, data, fn, one)
                })
                return $this
            }
        //elem.on(‘click‘,fn)   绑定事件
            if (!isString(selector) && !isFunction(callback) && callback !== false)
                callback = data, data = selector, selector = undefined        //elem.on(‘click‘,‘a‘,fn)  事件委托
            if (callback === undefined || data === false)
                callback = data, data = undefined

            if (callback === false) callback = returnFalse

            return $this.each(function(_, element){                    //回调函数,当执行时候就移除绑定的函数  然后执行改callback
                if (one) autoRemove = function(e){
                    remove(element, e.type, callback)
                    return callback.apply(this, arguments)
                }
          
                if (selector) delegator = function(e){
                    var evt, match = $(e.target).closest(selector, element).get(0)
                    if (match && match !== element) {
                        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)
            })
        }

  

bind,one,delegate,live全都是继承了并执行on函数
    $.fn.off = function(event, selector, callback){
            var $this = this
            if (event && !isString(event)) {
                $.each(event, function(type, fn){
                    $this.off(type, selector, fn)
                })
                return $this
            }

            if (!isString(selector) && !isFunction(callback) && callback !== false)
                callback = selector, selector = undefined

            if (callback === false) callback = returnFalse

            return $this.each(function(){
                remove(this, event, callback, selector)
            })
        }

  

所有的一定事件都是继承并执行该函数

   $.fn.trigger = function(event, args){
            event = (isString(event) || $.isPlainObject(event)) ? $.Event(event) : compatible(event)
            event._args = args
            return this.each(function(){
                // focus(),blur()直接调用
                if (event.type in focus && typeof this[event.type] == "function") this[event.type]()
                // items in the collection might not be DOM elements          //自定义的 事件 直接用 用creatEvent的事件可以指定用dispatcheEvent(e)
                else if (‘dispatchEvent‘ in this) this.dispatchEvent(event)          //获取到绑定的事件并执行,通过event找到 在 Handers中到到对应的函数 handlers.proxy执行
                else $(this).triggerHandler(event, args)
            })
        }

  

手动触发事件

$.Event = function(type, props) {
            if (!isString(type)) props = type, type = props.type
            var event = document.createEvent(specialEvents[type] || ‘Events‘), bubbles = true
            if (props) for (var name in props) (name == ‘bubbles‘) ? (bubbles = !!props[name]) : (event[name] = props[name])
            event.initEvent(type, bubbles, true)
            return compatible(event)
        }

    //创建一个Event对象,并且初始化事件对象,可以去看看creareEvent文档

  

代码仅供参考,具体功能可以自己扩展。

http://www.cnblogs.com/jiebba/p/6529854.html

http://www.cnblogs.com/jiebba    我的博客,来看吧!

如果有错误,请留言修改下 哦!

时间: 2024-07-29 06:03:47

非常适合新手的jq/zepto源码分析06 -- 事件模型的相关文章

非常适合新手的jq/zepto源码分析05

zepto的原型  $.fn  属性: constructor //构造行数 forEach: emptyArray.forEach, //都是原生数组的函数reduce: emptyArray.reduce,push: emptyArray.push,sort: emptyArray.sort,splice: emptyArray.splice,indexOf: emptyArray.indexOf, concat //合并数组,这里还包含了合并节点集合 add //添加节点集合 is //匹

zepto源码分析系列

如果你也开发移动端web,如果你也用zepto,应该值得你看看.有问题请留言. Zepto源码分析-架构 Zepto源码分析-zepto(DOM)模块 Zepto源码分析-callbacks模块 Zepto源码分析-event模块 Zepto源码分析-ajax模块 Zepto源码分析-form模块 Zepto源码分析-deferred模块 Zepto源码分析-动画(fx fx_method)模块 内容一定要200字一定要200字内容一定要200字一定要200字内容一定要200字一定要200字内容

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 ? ch

monkey源码分析之事件注入方法变化

在上一篇文章<Monkey源码分析之事件注入>中,我们看到了monkey在注入事件的时候用到了<Monkey源码分析番外篇之Android注入事件的三种方法比较>中的第一种方法,通过Internal API的WindowManager的injectKeyEvent之类的方法注入事件.这种方法在android api level 16也就是android4.1.2之后已经发生了变化: 在此之后注入事件的方式变成了使用InputManager的injectInputEvent方法了 而

Memcached源码分析之线程模型

作者:Calix 一)模型分析 memcached到底是如何处理我们的网络连接的? memcached通过epoll(使用libevent,下面具体再讲)实现异步的服务器,但仍然使用多线程,主要有两种线程,分别是“主线程”和“worker线程”,一个主线程,多个worker线程. 主线程负责监听网络连接,并且accept连接.当监听到连接时,accept后,连接成功,把相应的client fd丢给其中一个worker线程.worker线程接收主线程丢过来的client fd,加入到自己的epol

zepto源码分析-代码结构【转载】

本来想学习一下jQuery的源码,但由于jQuery的源码有10000多行,设计相当复杂,所以决定从zepto开始,分析一个成熟的框架的代码结构及执行步骤. 网上也有很多zepto的源码分析,有的给源码添加注释,有的谈与jQuery的不同,但是都没有系统的讲解zepto框架的代码结构及初始化Zepto对象的过程. 准备 默认你已经对面向对象有一定的了解,本文是边实践边写的,虽有些乱,但好处是为大家提供了分析的思路. 英文文档. 中文文档 注意在文中$变量表示一个函数对象,而$()表示执行函数,他

Monkey源码分析之事件注入

本系列的上一篇文章<Monkey源码分析之事件源>中我们描述了monkey是怎么从事件源取得命令,然后将命令转换成事件放到事件队列里面的,但是到现在位置我们还没有了解monkey里面的事件是怎么一回事,本篇文章就以这个问题作为切入点,尝试去搞清楚monkey的event架构是怎么样的,然后为什么是这样架构的,以及它又是怎么注入事件来触发点击等动作的. 在看这篇文章之前,希望大家最好先去看下另外几篇博文,这样理解起来就会更容易更清晰了: <Monkey源码分析番外篇之Android注入事件

Spring AMQP 源码分析 06 - 手动消息确认

### 准备 ## 目标 了解 Spring AMQP 如何手动确认消息已成功消费 ## 前置知识 <Spring AMQP 源码分析 04 - MessageListener> ## 相关资源 Offical doc:<http://docs.spring.io/spring-amqp/docs/1.7.3.RELEASE/reference/html/_reference.html#message-listener-adapter> Sample code:<https:

Zepto源码分析-event模块

源码注释 // Zepto.js // (c) 2010-2015 Thomas Fuchs // Zepto.js may be freely distributed under the MIT license. ;(function($){ var _zid = 1, undefined, slice = Array.prototype.slice, isFunction = $.isFunction, isString = function(obj){ return typeof obj