New implementation of eventlisteners module
parent
fd539435f6
commit
8ca33c916b
@ -1,62 +1,79 @@
|
||||
var is = require('../is');
|
||||
|
||||
function arrInvoker(arr) {
|
||||
return function() {
|
||||
if (!arr.length) return;
|
||||
// Special case when length is two, for performance
|
||||
arr.length === 2 ? arr[0](arr[1]) : arr[0].apply(undefined, arr.slice(1));
|
||||
};
|
||||
function invokeHandler(handler, vnode, event) {
|
||||
if (typeof handler === "function") {
|
||||
// call function handler
|
||||
handler.call(vnode, event);
|
||||
} else if (typeof handler === "object") {
|
||||
// call handler with arguments
|
||||
if (typeof handler[0] === "function") {
|
||||
// special case for single argument for performance
|
||||
handler.length === 2 ?
|
||||
handler[0].call(vnode, handler[1], event) :
|
||||
handler[0].apply(vnode, handler.slice(1).concat(event));
|
||||
} else {
|
||||
// call multiple handlers
|
||||
for (var i = 0; i < handler.length; i++) {
|
||||
invokeHandler(handler[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function handleEvent(event, vnode) {
|
||||
var name = event.type,
|
||||
on = vnode.data.on;
|
||||
|
||||
// call event handler(s) if exists
|
||||
if (on && on[name]) {
|
||||
invokeHandler(on[name], vnode, event);
|
||||
}
|
||||
}
|
||||
|
||||
function fnInvoker(o) {
|
||||
return function(ev) {
|
||||
if (o.fn === null) return;
|
||||
o.fn(ev);
|
||||
};
|
||||
function createListener() {
|
||||
return function handler(event) {
|
||||
handleEvent(event, handler.vnode);
|
||||
}
|
||||
}
|
||||
|
||||
function updateEventListeners(oldVnode, vnode) {
|
||||
var name, cur, old, elm = vnode.elm,
|
||||
oldOn = oldVnode.data.on, on = vnode.data.on;
|
||||
|
||||
if (!on && !oldOn) return;
|
||||
on = on || {};
|
||||
oldOn = oldOn || {};
|
||||
|
||||
for (name in on) {
|
||||
cur = on[name];
|
||||
old = oldOn[name];
|
||||
if (old === undefined) {
|
||||
if (is.array(cur)) {
|
||||
elm.addEventListener(name, arrInvoker(cur));
|
||||
} else {
|
||||
cur = {fn: cur};
|
||||
on[name] = cur;
|
||||
elm.addEventListener(name, fnInvoker(cur));
|
||||
var oldOn = oldVnode.data.on,
|
||||
oldListener = oldVnode.listener,
|
||||
oldElm = oldVnode.elm,
|
||||
on = vnode && vnode.data.on,
|
||||
elm = vnode && vnode.elm;
|
||||
|
||||
// improvement for immutable handlers
|
||||
if (oldElm === elm && oldOn === on) {
|
||||
return;
|
||||
}
|
||||
|
||||
// remove existing listeners which no longer used
|
||||
if (oldOn && oldListener) {
|
||||
for (var _name in oldOn) {
|
||||
// remove listener if element was changed or existing listener(s) removed
|
||||
if (elm !== oldElm || !on || !on[_name]) {
|
||||
oldElm.removeEventListener(_name, oldListener, false);
|
||||
}
|
||||
} else if (is.array(old)) {
|
||||
// Deliberately modify old array since it's captured in closure created with `arrInvoker`
|
||||
old.length = cur.length;
|
||||
for (var i = 0; i < old.length; ++i) old[i] = cur[i];
|
||||
on[name] = old;
|
||||
} else {
|
||||
old.fn = cur;
|
||||
on[name] = old;
|
||||
}
|
||||
}
|
||||
if (oldOn) {
|
||||
for (name in oldOn) {
|
||||
if (on[name] === undefined) {
|
||||
var old = oldOn[name];
|
||||
if (is.array(old)) {
|
||||
old.length = 0;
|
||||
}
|
||||
else {
|
||||
old.fn = null;
|
||||
}
|
||||
|
||||
// add new listeners which has not already attached
|
||||
if (on) {
|
||||
// reuse existing listener or create new
|
||||
var listener = vnode.listener = oldVnode.listener || createListener();
|
||||
// update vnode for listener
|
||||
listener.vnode = vnode;
|
||||
|
||||
for (var name in on) {
|
||||
// add listener if element was changed or new listener(s) added
|
||||
if (elm !== oldElm || !oldOn || !oldOn[name]) {
|
||||
elm.addEventListener(name, listener, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {create: updateEventListeners, update: updateEventListeners};
|
||||
module.exports = {
|
||||
create: updateEventListeners,
|
||||
update: updateEventListeners,
|
||||
destroy: updateEventListeners
|
||||
};
|
||||
|
Loading…
Reference in New Issue