zoukankan      html  css  js  c++  java
  • 非常适合新手的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    我的博客,来看吧!

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

  • 相关阅读:
    esp8266(3) Arduino通过ESP8266连接和获取网站源代码
    esp8266(2) 智能配置
    图像工程考试
    Arduino IDE for ESP8266 ()esp8266项目 WIFI攻击器
    esp8266(1) 手机+Arduino+esp8266通信
    esp8266(0) AT指令
    ROS ZED
    手机APP
    Arduino IDE for ESP8266教程(0)配置IDE
    Arduino 433 + 串口
  • 原文地址:https://www.cnblogs.com/jiebba/p/6532583.html
Copyright © 2011-2022 走看看