inferno
inferno copied to clipboard
[feature request] support capturing event handlers
React has support for defining event handlers that use capturing rather than bubbling:
To register an event handler for the capture phase, append
Captureto the event name; for example, instead of usingonClick, you would useonClickCaptureto handle the click event in the capture phase.
I'd like for this to exist in Inferno too.
If #1434 is merged, then adding this functionality won't be too difficult since we'll be using addEventListener and we can change the args if "Capture" is found at the end of the event prop.
What are people's thoughts?
It would also be great to support passive event listeners. However I don't know how React defines Passive and Capture ... Also what happens when browser vendors extend the options. It would be better to have future proof API and put that into inferno-compat
There's an interesting discussion about this in React here: https://github.com/facebook/react/issues/6436
I can expand on capture events for React (I'm in the middle of looking at the event system for React). React allows most events to work in the "capture" phase by appending "Capture" to the end of the prop name, i.e. onClickCapture.
A captured event gets triggered in the opposite ordering of bubbling (so before bubbled events get fired). React collects the DOM node hierarchy and traverses through them in two phases – capture first, then bubble. This is kind of like how Inferno works already, except Inferno only has one phase – bubbling. To make this work, you'd need to collect the DOM nodes [document > A > B > C] and then loop through them in those orders.
After thinking about this a little more I think a future proof API is actually a good idea. I'm not sure React's way of appending "Capture" is the best way to do this.
In the thread I linked above there were a few different suggestions, some which stood out to me were:
import { eventHandler } from 'inferno';
<div onClick={eventHandler(listener, options}} />
<div onClick={{ handler, options }} />
In both cases if there are future changes to the addEventListener API then these should be future proof.
Agreed, this is something we're looking at too. I thought I'd add what React does right now anyway for context. A better API might be to leverage a JSX node that the compiler can optimize away at build time:
import { Event } from 'inferno';
<Event type="click" bubbles={false} passive={true} on={e => ...}>
<div>Hello world</div>
</Event>
This would improve performance and reduce code size. The event can also fire for multiple children, which makes it extremely powerful and far more composable than attaching props to a VNode. In fact you could remove the controlled components system entire.
const onChange = (value, key) => {
this.setState({[key]: value});
}
<ChangeEvent type="value" on={onChange}>
<input key="name" type="text" value={this.state.name} />
<input key="age" type="text" value={this.state.age} />
</ChangeEvent>