mirror of
https://github.com/zoriya/react-native-web.git
synced 2026-05-28 16:45:17 +00:00
[fix] low-level performance tuning
createDOMProps: avoid using default parameters as Babel compiles the function to calls using 'arguments', which Chrome flags as a deopt. Replace 'typeof' calls with slightly faster calls to constructor. onLayout: batch layout measurements in a single requestAnimationFrame. Close #490
This commit is contained in:
committed by
Nicolas Gallagher
parent
d57fb6407a
commit
a9c7b38df9
@@ -1,4 +1,5 @@
|
||||
import requestAnimationFrame from 'fbjs/lib/requestAnimationFrame';
|
||||
import setImmediate from 'fbjs/lib/setImmediate';
|
||||
import setValueForStyles from '../../vendor/setValueForStyles';
|
||||
|
||||
const getRect = node => {
|
||||
@@ -14,9 +15,14 @@ const getRect = node => {
|
||||
return { height, left, top, width };
|
||||
};
|
||||
|
||||
const measureLayout = (node, relativeToNativeNode, callback) => {
|
||||
requestAnimationFrame(() => {
|
||||
let hasRequestedAnimationFrame = false;
|
||||
const measureLayoutQueue = [];
|
||||
|
||||
const processLayoutQueue = () => {
|
||||
measureLayoutQueue.splice(0, 250).forEach((item) => {
|
||||
const [node, relativeToNativeNode, callback] = item;
|
||||
const relativeNode = relativeToNativeNode || (node && node.parentNode);
|
||||
|
||||
if (node && relativeNode) {
|
||||
const relativeRect = getRect(relativeNode);
|
||||
const { height, left, top, width } = getRect(node);
|
||||
@@ -24,7 +30,23 @@ const measureLayout = (node, relativeToNativeNode, callback) => {
|
||||
const y = top - relativeRect.top;
|
||||
callback(x, y, width, height, left, top);
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
if (measureLayoutQueue.length > 0) {
|
||||
setImmediate(processLayoutQueue);
|
||||
}
|
||||
}
|
||||
|
||||
const measureLayout = (node, relativeToNativeNode, callback) => {
|
||||
if (!hasRequestedAnimationFrame) {
|
||||
requestAnimationFrame(() => {
|
||||
hasRequestedAnimationFrame = false;
|
||||
processLayoutQueue();
|
||||
});
|
||||
}
|
||||
|
||||
hasRequestedAnimationFrame = true;
|
||||
measureLayoutQueue.push([node, relativeToNativeNode, callback]);
|
||||
};
|
||||
|
||||
const UIManager = {
|
||||
|
||||
@@ -44,14 +44,12 @@ const createDOMElement = (component, props) => {
|
||||
|
||||
// normalize DOM events to match React Native events
|
||||
// TODO: move this out of the render path
|
||||
for (const prop in domProps) {
|
||||
if (Object.prototype.hasOwnProperty.call(domProps, prop)) {
|
||||
const isEventHandler = typeof prop === 'function' && eventHandlerNames[prop];
|
||||
if (isEventHandler) {
|
||||
domProps[prop] = wrapEventHandler(prop);
|
||||
}
|
||||
Object.keys(domProps).forEach((prop) => {
|
||||
const isEventHandler = typeof prop === 'function' && eventHandlerNames[prop];
|
||||
if (isEventHandler) {
|
||||
domProps[prop] = wrapEventHandler(prop);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return <Component {...domProps} />;
|
||||
};
|
||||
|
||||
@@ -39,7 +39,11 @@ const pointerEventStyles = StyleSheet.create({
|
||||
|
||||
const resolver = style => StyleRegistry.resolve(style);
|
||||
|
||||
const createDOMProps = (rnProps, resolveStyle = resolver) => {
|
||||
const createDOMProps = (rnProps, resolveStyle) => {
|
||||
if (!resolveStyle) {
|
||||
resolveStyle = resolver;
|
||||
}
|
||||
|
||||
const props = rnProps || emptyObject;
|
||||
const {
|
||||
accessibilityLabel,
|
||||
@@ -72,19 +76,19 @@ const createDOMProps = (rnProps, resolveStyle = resolver) => {
|
||||
if (accessible === true) {
|
||||
domProps.tabIndex = AccessibilityUtil.propsToTabIndex(props);
|
||||
}
|
||||
if (typeof accessibilityLabel === 'string') {
|
||||
if (accessibilityLabel && accessibilityLabel.constructor === String) {
|
||||
domProps['aria-label'] = accessibilityLabel;
|
||||
}
|
||||
if (typeof accessibilityLiveRegion === 'string') {
|
||||
if (accessibilityLiveRegion && accessibilityLiveRegion.constructor === String) {
|
||||
domProps['aria-live'] = accessibilityLiveRegion === 'none' ? 'off' : accessibilityLiveRegion;
|
||||
}
|
||||
if (typeof className === 'string' && className !== '') {
|
||||
if (className && className.constructor === String) {
|
||||
domProps.className = domProps.className ? `${domProps.className} ${className}` : className;
|
||||
}
|
||||
if (importantForAccessibility === 'no-hide-descendants') {
|
||||
domProps['aria-hidden'] = true;
|
||||
}
|
||||
if (typeof role === 'string') {
|
||||
if (role && role.constructor === String) {
|
||||
domProps.role = role;
|
||||
if (role === 'button') {
|
||||
domProps.type = 'button';
|
||||
@@ -92,13 +96,13 @@ const createDOMProps = (rnProps, resolveStyle = resolver) => {
|
||||
domProps.rel = `${domProps.rel || ''} noopener noreferrer`;
|
||||
}
|
||||
}
|
||||
if (style != null) {
|
||||
if (style) {
|
||||
domProps.style = style;
|
||||
}
|
||||
if (typeof testID === 'string') {
|
||||
if (testID && testID.constructor === String) {
|
||||
domProps['data-testid'] = testID;
|
||||
}
|
||||
if (typeof type === 'string') {
|
||||
if (type && type.constructor === String) {
|
||||
domProps.type = type;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user