Parameterized Event Handler Invocation
See original GitHub issueI have found two problems a problem with parameterized event handling, demonstrated in this fiddle.
First, the global and vm onevent
handlers are invoked multiple times, once for each parameterized handler found.
Second, parameterized event handlers are invoked in top-down order, from the outermost handler to the innermost, which is the opposite of normal onxxx
event handlers.
Also, I also note that the vm and global handlers are invoked regardless of whether an element-specific handler has returned false – this may or may not be desirable/defensible, but it absolutely should be clearly documented (it might be, already, but I don’t recall seeing it).
function AppView(vm) {
return function(vm) {
return ve("div", {
onkeydown: bindVm(keyDown1, vm),
}, [
ve("div.key-target", {
tabindex: 0,
onkeydown: bindVm(keyDown2, vm),
}, [
ve("div", "Handler 1: "+message1),
ve("div", "Handler 2: "+message2),
]),
]);
};
}
function bindVm(hdl,vm) {
return [ hdl,vm ];
//return (evt) => { if(hdl(vm,evt)===false) { evt.stopPropagation(); evt.preventDefault(); } }
}
As demonstrated, keyDown1
is invoked before keyDown2
. But if the bindVm
return is changed, invocation order will be the expected 2, then 1.
This is hugely significant in terms of logically cooperating handlers; it’s very common to want to handle an event only if a more specific handler has not already done so (as the fiddle demonstrates). This totally blindsided me, and renders parameterized event handlers of no practical use.
If it cannot be changed for reasons of compatibility, I believe a global, and per-vm option is needed to reverse this. But I, personally, would consider this a bug.
The problem seems to be in ancestEvDefs
, using unshift
instead of push
(which is also less efficient):
function ancestEvDefs(type, node) {
var ontype = "on" + type, evDef, attrs, evDefs = [];
while (node) {
if (attrs = node.attrs) {
if ((evDef = attrs[ontype]) && isArr(evDef))
{ evDefs.unshift(evDef); }
}
node = node.parent;
}
return evDefs;
}
Issue Analytics
- State:
- Created 2 years ago
- Comments:27 (11 by maintainers)
PS, you dont need to tag me in every comment. just the first issue or PR comment.
there is no x axis. look at the timings in the summary.
if we can keep the overhead to within what’s above, i’m okay with removing the delegation/simulation. go ahead and implement the non-delegated strategy for parameterized listeners in another PR and i’ll take a look 👍