mirror of
https://github.com/zoriya/react-native-web.git
synced 2026-06-02 02:25:22 +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 requestAnimationFrame from 'fbjs/lib/requestAnimationFrame';
|
||||||
|
import setImmediate from 'fbjs/lib/setImmediate';
|
||||||
import setValueForStyles from '../../vendor/setValueForStyles';
|
import setValueForStyles from '../../vendor/setValueForStyles';
|
||||||
|
|
||||||
const getRect = node => {
|
const getRect = node => {
|
||||||
@@ -14,9 +15,14 @@ const getRect = node => {
|
|||||||
return { height, left, top, width };
|
return { height, left, top, width };
|
||||||
};
|
};
|
||||||
|
|
||||||
const measureLayout = (node, relativeToNativeNode, callback) => {
|
let hasRequestedAnimationFrame = false;
|
||||||
requestAnimationFrame(() => {
|
const measureLayoutQueue = [];
|
||||||
|
|
||||||
|
const processLayoutQueue = () => {
|
||||||
|
measureLayoutQueue.splice(0, 250).forEach((item) => {
|
||||||
|
const [node, relativeToNativeNode, callback] = item;
|
||||||
const relativeNode = relativeToNativeNode || (node && node.parentNode);
|
const relativeNode = relativeToNativeNode || (node && node.parentNode);
|
||||||
|
|
||||||
if (node && relativeNode) {
|
if (node && relativeNode) {
|
||||||
const relativeRect = getRect(relativeNode);
|
const relativeRect = getRect(relativeNode);
|
||||||
const { height, left, top, width } = getRect(node);
|
const { height, left, top, width } = getRect(node);
|
||||||
@@ -24,7 +30,23 @@ const measureLayout = (node, relativeToNativeNode, callback) => {
|
|||||||
const y = top - relativeRect.top;
|
const y = top - relativeRect.top;
|
||||||
callback(x, y, width, height, left, 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 = {
|
const UIManager = {
|
||||||
|
|||||||
@@ -44,14 +44,12 @@ const createDOMElement = (component, props) => {
|
|||||||
|
|
||||||
// normalize DOM events to match React Native events
|
// normalize DOM events to match React Native events
|
||||||
// TODO: move this out of the render path
|
// TODO: move this out of the render path
|
||||||
for (const prop in domProps) {
|
Object.keys(domProps).forEach((prop) => {
|
||||||
if (Object.prototype.hasOwnProperty.call(domProps, prop)) {
|
const isEventHandler = typeof prop === 'function' && eventHandlerNames[prop];
|
||||||
const isEventHandler = typeof prop === 'function' && eventHandlerNames[prop];
|
if (isEventHandler) {
|
||||||
if (isEventHandler) {
|
domProps[prop] = wrapEventHandler(prop);
|
||||||
domProps[prop] = wrapEventHandler(prop);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
|
|
||||||
return <Component {...domProps} />;
|
return <Component {...domProps} />;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -39,7 +39,11 @@ const pointerEventStyles = StyleSheet.create({
|
|||||||
|
|
||||||
const resolver = style => StyleRegistry.resolve(style);
|
const resolver = style => StyleRegistry.resolve(style);
|
||||||
|
|
||||||
const createDOMProps = (rnProps, resolveStyle = resolver) => {
|
const createDOMProps = (rnProps, resolveStyle) => {
|
||||||
|
if (!resolveStyle) {
|
||||||
|
resolveStyle = resolver;
|
||||||
|
}
|
||||||
|
|
||||||
const props = rnProps || emptyObject;
|
const props = rnProps || emptyObject;
|
||||||
const {
|
const {
|
||||||
accessibilityLabel,
|
accessibilityLabel,
|
||||||
@@ -72,19 +76,19 @@ const createDOMProps = (rnProps, resolveStyle = resolver) => {
|
|||||||
if (accessible === true) {
|
if (accessible === true) {
|
||||||
domProps.tabIndex = AccessibilityUtil.propsToTabIndex(props);
|
domProps.tabIndex = AccessibilityUtil.propsToTabIndex(props);
|
||||||
}
|
}
|
||||||
if (typeof accessibilityLabel === 'string') {
|
if (accessibilityLabel && accessibilityLabel.constructor === String) {
|
||||||
domProps['aria-label'] = accessibilityLabel;
|
domProps['aria-label'] = accessibilityLabel;
|
||||||
}
|
}
|
||||||
if (typeof accessibilityLiveRegion === 'string') {
|
if (accessibilityLiveRegion && accessibilityLiveRegion.constructor === String) {
|
||||||
domProps['aria-live'] = accessibilityLiveRegion === 'none' ? 'off' : accessibilityLiveRegion;
|
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;
|
domProps.className = domProps.className ? `${domProps.className} ${className}` : className;
|
||||||
}
|
}
|
||||||
if (importantForAccessibility === 'no-hide-descendants') {
|
if (importantForAccessibility === 'no-hide-descendants') {
|
||||||
domProps['aria-hidden'] = true;
|
domProps['aria-hidden'] = true;
|
||||||
}
|
}
|
||||||
if (typeof role === 'string') {
|
if (role && role.constructor === String) {
|
||||||
domProps.role = role;
|
domProps.role = role;
|
||||||
if (role === 'button') {
|
if (role === 'button') {
|
||||||
domProps.type = 'button';
|
domProps.type = 'button';
|
||||||
@@ -92,13 +96,13 @@ const createDOMProps = (rnProps, resolveStyle = resolver) => {
|
|||||||
domProps.rel = `${domProps.rel || ''} noopener noreferrer`;
|
domProps.rel = `${domProps.rel || ''} noopener noreferrer`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (style != null) {
|
if (style) {
|
||||||
domProps.style = style;
|
domProps.style = style;
|
||||||
}
|
}
|
||||||
if (typeof testID === 'string') {
|
if (testID && testID.constructor === String) {
|
||||||
domProps['data-testid'] = testID;
|
domProps['data-testid'] = testID;
|
||||||
}
|
}
|
||||||
if (typeof type === 'string') {
|
if (type && type.constructor === String) {
|
||||||
domProps.type = type;
|
domProps.type = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user