-
Notifications
You must be signed in to change notification settings - Fork 47.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
DO NOT MERGE: Investigate switching out event delegation for direct attachment (mostly) #11550
Changes from all commits
0fcbfbd
fa2501f
ca75e2e
cd44f7a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -13,13 +13,31 @@ import { | |
trapBubbledEvent, | ||
trapCapturedEvent, | ||
} from './ReactDOMEventListener'; | ||
import {DOCUMENT_NODE, DOCUMENT_FRAGMENT_NODE} from '../shared/HTMLNodeType'; | ||
import isEventSupported from './isEventSupported'; | ||
import BrowserEventConstants from './BrowserEventConstants'; | ||
|
||
export * from 'events/ReactEventEmitterMixin'; | ||
|
||
var {topLevelTypes} = BrowserEventConstants; | ||
|
||
const forceDelegation = { | ||
topMouseOver: 1, | ||
topMouseOut: 2, | ||
topMouseEnter: 3, | ||
topMouseLeave: 4, | ||
}; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why do these need delegation? I wonder what the likelihood of this growing annoyingly is? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We need this so that the EnterLeavePlugin event plugin works with elements React isn't watching. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. blah that's annoying, this should need to include There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. also did we end up some place on using the native event vs continuing to polyfill this forever? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah. Still I can't help but wonder if there's work that could be done here to do the attachment local to the event plugin. It's a bummer that ReactBrowserEventEmitter and EnterLeavePlugin are coupled like this. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is a similar problem for change events on inputs. We have to attach change events to controlled inputs even if there isn't an event listener. This is so that controlled inputs that don't have IMO, we should warn users when they don't have a change event and tell them to use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Let's give it a look. It looks like we might be able to use the native event now, but the support matrix for We should do this research, kill the event plugin if we can, which I think would also let us get rid of some tree traversal methods specific to this event. At the very least we should update all of those question marks on MDN. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I did the basic work checking for support, and we definitely can use the native event, the problem is Portals now. naive approach: #10247 In terms of moving attachment to the plugin, there used to be (still are?) hooks on the plugins that would get called for this sort of thing, something like |
||
|
||
function documentForRoot(rootContainerElement, registrationName) { | ||
var isDocumentOrFragment = | ||
rootContainerElement.nodeType === DOCUMENT_NODE || | ||
rootContainerElement.nodeType === DOCUMENT_FRAGMENT_NODE; | ||
|
||
return isDocumentOrFragment | ||
? rootContainerElement | ||
: rootContainerElement.ownerDocument; | ||
} | ||
|
||
/** | ||
* Summary of `ReactBrowserEventEmitter` event handling: | ||
* | ||
|
@@ -115,15 +133,22 @@ function getListeningForDocument(mountAt) { | |
* @param {string} registrationName Name of listener (e.g. `onClick`). | ||
* @param {object} contentDocumentHandle Document which owns the container | ||
*/ | ||
export function listenTo(registrationName, contentDocumentHandle) { | ||
export function listenTo(registrationName, contentDocumentHandle, root) { | ||
var mountAt = contentDocumentHandle; | ||
var isListening = getListeningForDocument(mountAt); | ||
var dependencies = registrationNameDependencies[registrationName]; | ||
|
||
for (var i = 0; i < dependencies.length; i++) { | ||
var dependency = dependencies[i]; | ||
|
||
if (!(isListening.hasOwnProperty(dependency) && isListening[dependency])) { | ||
if (dependency === 'topWheel') { | ||
if (forceDelegation.hasOwnProperty(dependency)) { | ||
trapBubbledEvent( | ||
dependency, | ||
topLevelTypes[dependency], | ||
documentForRoot(root), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. isn't There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🙈. I'll look into this :) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fixed in 68b42c2 |
||
); | ||
} else if (dependency === 'topWheel') { | ||
if (isEventSupported('wheel')) { | ||
trapBubbledEvent('topWheel', 'wheel', mountAt); | ||
} else if (isEventSupported('mousewheel')) { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
for these, is there a reason why we were calling them out specifically here vs in the
ensureListeningTo
above? Do they need to probably be attached likeonChange
now?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As far as I can tell, this is just a pre-emptive attachment because
ensureListeningTo
attaches on the owner document, not the DOM element. We need these here because they don't bubble, so there must be a listener on the element for the synthetic event system to know about it.I think there is a change we could send to master here. We can attach
reset
,submit
,load
, etc... directly on the element. I do not think the savings is substantial because these events are almost only ever added to these elements (when was the last time you attachedonError
on a div or button?)I'm going to check to see if we still need
onChange
to attach here.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
☝️ edited with some clarification.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Made it consistent in 68b42c2
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ah so since everything is being attached directly there is no need to handle it here anymore 👍 right