首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 网站开发 > Web前端 >

KISSY.Event 读码札记

2012-10-07 
KISSY.Event 读码笔记/*** @moduleevent* @authorlifesinger@gmail.com*/KISSY.add(event, function(S,

KISSY.Event 读码笔记

/*** @module  event* @author  lifesinger@gmail.com*/KISSY.add('event', function(S, undef) {    var doc = document,        DOM = S.DOM,        simpleAdd = doc.addEventListener ?            function(el, type, fn, capture) {                if (el.addEventListener) {                    el.addEventListener(type, fn, !!capture);                }            } :            function(el, type, fn) {                if (el.attachEvent) {                    el.attachEvent('on' + type, fn);                }            },        simpleRemove = doc.removeEventListener ?            function(el, type, fn, capture) {                if (el.removeEventListener) {                    el.removeEventListener(type, fn, !!capture);                }            } :            function(el, type, fn) {                if (el.detachEvent) {                    el.detachEvent('on' + type, fn);                }            }, //红色部分的是原生的事件加载        EVENT_GUID = 'ksEventTargetId',//标识符        SPACE = ' ',        guid = S.now(),//时间戳        // { id: { target: el, events: { type: { handle: obj, listeners: [...] } } }, ... }        cache = { };//缓存    var Event = {//定义一个Event对象        EVENT_GUID: EVENT_GUID,        // such as: { 'mouseenter' : { fix: 'mouseover', handle: fn } }        special: { },        /**         * Adds an event listener.         * @param target {Element} An element or custom EventTarget to assign the listener to.         * @param type {String} The type of event to append.         * @param fn {Function} The event handler.         * @param scope {Object} (optional) The scope (this reference) in which the handler function is executed.         */        add: function(target, type, fn, scope /* optional */) {//添加一个事件            if (batch('add', target, type, fn, scope)) return;//如果需要batch做一下批量,通过batch的逻辑            // Event.add([dom,dom])            //getID            var id = getID(target), isNativeEventTarget,                special, events, eventHandle, fixedType, capture;            // 不是有效的 target 或 参数不对            if (id === -1 || !type || !S.isFunction(fn)) return;            // 还没有添加过任何事件            if (!id) {//如果目前的对象没有添加过id                setID(target, (id = guid++));//set一个Id,并在cache里面存一个对应的对象,保存这个target和它对应的事件。                cache[id] = {                    target: target,                    events: { }                };            }            // 没有添加过该类型事件            events = cache[id].events;//events用来保存这个cache的events,用events来存储一个对象对应的event对象们            if (!events[type]) {                isNativeEventTarget = !target.isCustomEventTarget;                special = ((isNativeEventTarget || target._supportSpecialEvent)                    && Event.special[type]) || { };                eventHandle = function(event, eventData) {//eventHandle函数的定义,eventHandle是对事件添加的一层封装,原生的事件函数,只会有event这一个参数                    if (!event || !event.fixed) {                        event = new S.EventObject(target, event, type);//新new一个EventObject                    }                    if (S.isPlainObject(eventData)) {//把eventData mix到event对象上面,这里都没有区分是不是元素的事件。                        //protect type                        var typeo = event.type;                        S.mix(event, eventData);                        event.type = typeo;                    }                    if (special['setup']) {//如果是原生的事件或者是特殊的自定义事件,并定义了special方法,就通过special的setup方法来执行这个                        special['setup'](event);                    }                    return (special.handle || Event._handle)(target, event);//返回值看special里面是否定义了handle,如果没有,就调用Event的_handle来处理target和event,默认的自定义事件的fire会来调用Event._handle方法,                };                events[type] = {//在events对象下面的类型下面建立对应的type的对象                    handle: eventHandle,//每一个类型的事件的eventHandle都会保存在此一份,只不过原生的js会再用simpleAdd再做一层原生的调用                    listeners: []                };                fixedType = special.fix || type;//fix capture                capture = special['capture'];                if (special['init']) {                    special['init'].apply(null, S.makeArray(arguments));                }                if (isNativeEventTarget && special.fix !== false) {//如果是原生的事件并且fix不是false,那么就用原生的添加事件。                    simpleAdd(target, fixedType, eventHandle, capture);                }            }            // 增加 listener            events[type].listeners.push({fn: fn, scope: scope || target});//对events对应的类型的listener下面push进对应的fn和eventHandle。        },        __getListeners:function(target, type) {//获取一个event对象的Listeners            var events = Event.__getEvents(target) || {},                eventsType,                listeners = [];            if ((eventsType = events[type])) {                listeners = eventsType.listeners;            }            return listeners;        },        __getEvents:function(target) {//获取一个对象上面的事件            var id = getID(target),c,                events;            if (id === -1) return; // 不是有效的 target            if (!id || !(c = cache[id])) return; // 无 cache            if (c.target !== target) return; // target 不匹配            events = c.events || { };            return events;        },        /**         * Detach an event or set of events from an element.         */        remove: function(target, type /* optional */, fn /* optional */, scope /* optional */) {            if (batch('remove', target, type, fn, scope)) return;            var events = Event.__getEvents(target),                id = getID(target),                eventsType,                listeners,                len,                i,                j,                t,                isNativeEventTarget = !target.isCustomEventTarget,//isCustomEventTarget是外部传入的一个配置属性                special = ((isNativeEventTarget || target._supportSpecialEvent)                    && Event.special[type]) || { };            if (events === undefined) return;            scope = scope || target;            if ((eventsType = events[type])) {                listeners = eventsType.listeners;                len = listeners.length;                // 移除 fn                if (S.isFunction(fn) && len) {                    for (i = 0,j = 0,t = []; i < len; ++i) {                        if (fn !== listeners[i].fn                            || scope !== listeners[i].scope) {                            t[j++] = listeners[i];                        }                    }                    eventsType.listeners = t;                    len = t.length;                }                // remove(el, type) or fn 已移除光                if (fn === undef || len === 0) {                    if (!target.isCustomEventTarget) {                        special = Event.special[type] || { };                        if (special.fix !== false)                            simpleRemove(target, special.fix || type, eventsType.handle);                    }                    delete events[type];                }            }            if (special.destroy) {                special.destroy.apply(null, S.makeArray(arguments));            }            // remove(el) or type 已移除光            if (type === undef || S.isEmptyObject(events)) {                for (type in events) {                    Event.remove(target, type);                }                delete cache[id];                removeID(target);            }        },        _handle: function(target, event) {            /* As some listeners may remove themselves from the             event, the original array length is dynamic. So,             let's make a copy of all listeners, so we are             sure we'll call all of them.*/            var listeners = Event.__getListeners(target, event.type);            listeners = listeners.slice(0);            var ret,                gRet,                i = 0,                len = listeners.length,                listener;            for (; i < len; ++i) {                listener = listeners[i];                ret = listener.fn.call(listener.scope, event);                //有一个 false,最终结果就是 false                if (gRet !== false) {                    gRet = ret;                }                // 和 jQuery 逻辑保持一致                // return false 等价 preventDefault + stopProgation                if (ret !== undefined) {                    event.result = ret;                    if (ret === false) {                        event.halt();                    }                }                if (event.isImmediatePropagationStopped) {                    break;                }            }            return gRet;        },        _getCache: function(id) {            return cache[id];        },        __getID:getID,        _simpleAdd: simpleAdd,        _simpleRemove: simpleRemove    };    // shorthand    Event.on = Event.add;    function batch(methodName, targets, types, fn, scope) {//batch方法,在add或者是remove之前做一层批量的处理        // on('#id tag.className', type, fn)        if (S.isString(targets)) {            targets = S.query(targets);//获取targets对象        }        // on([targetA, targetB], type, fn)        if (S.isArray(targets)) {//如果有多个targets,那么就在Event对象下面对应的方法下面传入参数,不处理多对象多事件的情况            S.each(targets, function(target) {                Event[methodName](target, types, fn, scope);            });            return true;        }        // on(target, 'click focus', fn)        if ((types = S.trim(types)) && types.indexOf(SPACE) > 0) {//一个对象有多个事件使用同一个事件函数            S.each(types.split(SPACE), function(type) {                Event[methodName](targets, type, fn, scope);            });            return true;        }    }    function getID(target) {//getID 如果是一个dom节点或一个对象,就取这个节点的EVENT_GUID属性,否则返回-1        return isValidTarget(target) ? DOM.data(target, EVENT_GUID) : -1;    }    function setID(target, id) {//setID,如果是一个dom节点或一个对象,就给这个节点加上一个EVENT_GUID属性        if (isValidTarget(target)) {            DOM.data(target, EVENT_GUID, id);        }    }    function removeID(target) {//removeID,删除一个dom节点或一个对象的EVENT_GUID属性        DOM.removeData(target, EVENT_GUID);    }    function isValidTarget(target) {//isValidTarget方法        // 3 - is text node        // 8 - is comment node        return target && target.nodeType !== 3 && target.nodeType !== 8;    }    S.Event = Event;});

热点排行