mirror of
https://github.com/zhigang1992/react-native-web.git
synced 2026-04-01 09:27:14 +08:00
Address avoidable object creation
This commit is contained in:
@@ -11,6 +11,7 @@ import invariant from 'fbjs/lib/invariant';
|
||||
import { unmountComponentAtNode } from 'react/lib/ReactMount';
|
||||
import renderApplication, { getApplication } from './renderApplication';
|
||||
|
||||
const emptyObject = {};
|
||||
const runnables = {};
|
||||
|
||||
type ComponentProvider = () => Component<any, any, any>
|
||||
@@ -41,8 +42,8 @@ class AppRegistry {
|
||||
|
||||
static registerComponent(appKey: string, getComponentFunc: ComponentProvider): string {
|
||||
runnables[appKey] = {
|
||||
getApplication: ({ initialProps } = {}) => getApplication(getComponentFunc(), initialProps),
|
||||
run: ({ initialProps, rootTag }) => renderApplication(getComponentFunc(), initialProps, rootTag)
|
||||
getApplication: ({ initialProps } = emptyObject) => getApplication(getComponentFunc(), initialProps),
|
||||
run: ({ initialProps = emptyObject, rootTag }) => renderApplication(getComponentFunc(), initialProps, rootTag)
|
||||
};
|
||||
return appKey;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import I18nManager from '../I18nManager';
|
||||
import multiplyStyleLengthValue from '../../modules/multiplyStyleLengthValue';
|
||||
|
||||
const emptyObject = {};
|
||||
|
||||
/**
|
||||
* Map of property names to their BiDi equivalent.
|
||||
*/
|
||||
@@ -64,38 +66,40 @@ const swapLtrRtl = (value:String): String => {
|
||||
return value === 'ltr' ? 'rtl' : value === 'rtl' ? 'ltr' : value;
|
||||
};
|
||||
|
||||
const i18nStyle = (style = {}) => {
|
||||
const i18nStyle = (style = emptyObject) => {
|
||||
const newStyle = {};
|
||||
for (const prop in style) {
|
||||
if (style.hasOwnProperty(prop)) {
|
||||
const indexOfNoFlip = prop.indexOf('$noI18n');
|
||||
if (!Object.prototype.hasOwnProperty.call(style, prop)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (I18nManager.isRTL) {
|
||||
if (PROPERTIES_TO_SWAP[prop]) {
|
||||
const newProp = flipProperty(prop);
|
||||
newStyle[newProp] = style[prop];
|
||||
} else if (PROPERTIES_SWAP_LEFT_RIGHT[prop]) {
|
||||
newStyle[prop] = swapLeftRight(style[prop]);
|
||||
} else if (PROPERTIES_SWAP_LTR_RTL[prop]) {
|
||||
newStyle[prop] = swapLtrRtl(style[prop]);
|
||||
} else if (prop === 'textShadowOffset') {
|
||||
newStyle[prop] = style[prop];
|
||||
newStyle[prop].width = additiveInverse(style[prop].width);
|
||||
} else if (prop === 'transform') {
|
||||
newStyle[prop] = style[prop].map(flipTransform);
|
||||
} else if (indexOfNoFlip > -1) {
|
||||
const newProp = prop.substring(0, indexOfNoFlip);
|
||||
newStyle[newProp] = style[prop];
|
||||
} else {
|
||||
newStyle[prop] = style[prop];
|
||||
}
|
||||
const indexOfNoFlip = prop.indexOf('$noI18n');
|
||||
|
||||
if (I18nManager.isRTL) {
|
||||
if (PROPERTIES_TO_SWAP[prop]) {
|
||||
const newProp = flipProperty(prop);
|
||||
newStyle[newProp] = style[prop];
|
||||
} else if (PROPERTIES_SWAP_LEFT_RIGHT[prop]) {
|
||||
newStyle[prop] = swapLeftRight(style[prop]);
|
||||
} else if (PROPERTIES_SWAP_LTR_RTL[prop]) {
|
||||
newStyle[prop] = swapLtrRtl(style[prop]);
|
||||
} else if (prop === 'textShadowOffset') {
|
||||
newStyle[prop] = style[prop];
|
||||
newStyle[prop].width = additiveInverse(style[prop].width);
|
||||
} else if (prop === 'transform') {
|
||||
newStyle[prop] = style[prop].map(flipTransform);
|
||||
} else if (indexOfNoFlip > -1) {
|
||||
const newProp = prop.substring(0, indexOfNoFlip);
|
||||
newStyle[newProp] = style[prop];
|
||||
} else {
|
||||
if (indexOfNoFlip > -1) {
|
||||
const newProp = prop.substring(0, indexOfNoFlip);
|
||||
newStyle[newProp] = style[prop];
|
||||
} else {
|
||||
newStyle[prop] = style[prop];
|
||||
}
|
||||
newStyle[prop] = style[prop];
|
||||
}
|
||||
} else {
|
||||
if (indexOfNoFlip > -1) {
|
||||
const newProp = prop.substring(0, indexOfNoFlip);
|
||||
newStyle[newProp] = style[prop];
|
||||
} else {
|
||||
newStyle[prop] = style[prop];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,8 +35,11 @@ const UIManager = {
|
||||
|
||||
updateView(node, props, component /* only needed to surpress React errors in development */) {
|
||||
for (const prop in props) {
|
||||
const value = props[prop];
|
||||
if (!Object.prototype.hasOwnProperty.call(props, prop)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const value = props[prop];
|
||||
switch (prop) {
|
||||
case 'style':
|
||||
// convert styles to DOM-styles
|
||||
|
||||
@@ -8,6 +8,8 @@ import StyleSheetPropType from '../../propTypes/StyleSheetPropType';
|
||||
import View from '../View';
|
||||
import React, { Component, PropTypes } from 'react';
|
||||
|
||||
const emptyObject = {};
|
||||
|
||||
const STATUS_ERRORED = 'ERRORED';
|
||||
const STATUS_LOADED = 'LOADED';
|
||||
const STATUS_LOADING = 'LOADING';
|
||||
@@ -52,7 +54,7 @@ class Image extends Component {
|
||||
};
|
||||
|
||||
static defaultProps = {
|
||||
style: {}
|
||||
style: emptyObject
|
||||
};
|
||||
|
||||
static resizeMode = ImageResizeMode;
|
||||
|
||||
@@ -17,6 +17,8 @@ import View from '../View';
|
||||
import ViewStylePropTypes from '../View/ViewStylePropTypes';
|
||||
import React, { Component, PropTypes } from 'react';
|
||||
|
||||
const emptyObject = {};
|
||||
|
||||
/* eslint-disable react/prefer-es6-class */
|
||||
const ScrollView = React.createClass({
|
||||
propTypes: {
|
||||
@@ -79,7 +81,7 @@ const ScrollView = React.createClass({
|
||||
if (typeof y === 'number') {
|
||||
console.warn('`scrollTo(y, x, animated)` is deprecated. Use `scrollTo({x: 5, y: 5, animated: true})` instead.');
|
||||
} else {
|
||||
({ x, y, animated } = y || {});
|
||||
({ x, y, animated } = y || emptyObject);
|
||||
}
|
||||
|
||||
this.getScrollResponder().scrollResponderScrollTo({ x: x || 0, y: y || 0, animated: animated !== false });
|
||||
|
||||
@@ -7,6 +7,7 @@ import UIManager from '../../apis/UIManager';
|
||||
import View from '../View';
|
||||
import React, { Component, PropTypes } from 'react';
|
||||
|
||||
const emptyObject = {};
|
||||
const thumbDefaultBoxShadow = '0px 1px 3px rgba(0,0,0,0.5)';
|
||||
const thumbFocusedBoxShadow = `${thumbDefaultBoxShadow}, 0 0 0 10px rgba(0,0,0,0.1)`;
|
||||
|
||||
@@ -28,7 +29,7 @@ class Switch extends Component {
|
||||
activeThumbColor: '#009688',
|
||||
activeTrackColor: '#A3D3CF',
|
||||
disabled: false,
|
||||
style: {},
|
||||
style: emptyObject,
|
||||
thumbColor: '#FAFAFA',
|
||||
trackColor: '#939393',
|
||||
value: false
|
||||
|
||||
@@ -40,25 +40,24 @@ class Text extends Component {
|
||||
onLayout,
|
||||
suppressHighlighting,
|
||||
/* eslint-enable */
|
||||
...other
|
||||
...otherProps
|
||||
} = this.props;
|
||||
|
||||
if (onPress) {
|
||||
other.onClick = onPress;
|
||||
other.onKeyDown = this._createEnterHandler(onPress);
|
||||
other.tabIndex = 0;
|
||||
otherProps.onClick = onPress;
|
||||
otherProps.onKeyDown = this._createEnterHandler(onPress);
|
||||
otherProps.tabIndex = 0;
|
||||
}
|
||||
|
||||
return createDOMElement('span', {
|
||||
...other,
|
||||
style: [
|
||||
styles.initial,
|
||||
style,
|
||||
!selectable && styles.notSelectable,
|
||||
numberOfLines === 1 && styles.singleLineStyle,
|
||||
onPress && styles.pressable
|
||||
]
|
||||
});
|
||||
otherProps.style = [
|
||||
styles.initial,
|
||||
style,
|
||||
!selectable && styles.notSelectable,
|
||||
numberOfLines === 1 && styles.singleLineStyle,
|
||||
onPress && styles.pressable
|
||||
];
|
||||
|
||||
return createDOMElement('span', otherProps);
|
||||
}
|
||||
|
||||
_createEnterHandler(fn) {
|
||||
|
||||
@@ -10,6 +10,8 @@ import UIManager from '../../apis/UIManager';
|
||||
import View from '../View';
|
||||
import { Component, PropTypes } from 'react';
|
||||
|
||||
const emptyObject = {};
|
||||
|
||||
/**
|
||||
* React Native events differ from W3C events.
|
||||
*/
|
||||
@@ -94,7 +96,7 @@ class TextInput extends Component {
|
||||
multiline: false,
|
||||
numberOfLines: 2,
|
||||
secureTextEntry: false,
|
||||
style: {}
|
||||
style: emptyObject
|
||||
};
|
||||
|
||||
blur() {
|
||||
@@ -153,7 +155,7 @@ class TextInput extends Component {
|
||||
selectionColor,
|
||||
selectTextOnFocus,
|
||||
/* eslint-enable */
|
||||
...other
|
||||
...otherProps
|
||||
} = this.props;
|
||||
|
||||
let type;
|
||||
@@ -186,8 +188,7 @@ class TextInput extends Component {
|
||||
|
||||
const component = multiline ? TextareaAutosize : 'input';
|
||||
|
||||
const props = {
|
||||
...other,
|
||||
Object.assign(otherProps, {
|
||||
autoCorrect: autoCorrect ? 'on' : 'off',
|
||||
dir: 'auto',
|
||||
onBlur: normalizeEventHandler(this._handleBlur),
|
||||
@@ -201,16 +202,16 @@ class TextInput extends Component {
|
||||
styles.initial,
|
||||
style
|
||||
]
|
||||
};
|
||||
});
|
||||
|
||||
if (multiline) {
|
||||
props.maxRows = maxNumberOfLines || numberOfLines;
|
||||
props.minRows = numberOfLines;
|
||||
otherProps.maxRows = maxNumberOfLines || numberOfLines;
|
||||
otherProps.minRows = numberOfLines;
|
||||
} else {
|
||||
props.type = type;
|
||||
otherProps.type = type;
|
||||
}
|
||||
|
||||
return createDOMElement(component, props);
|
||||
return createDOMElement(component, otherProps);
|
||||
}
|
||||
|
||||
_handleBlur = (e) => {
|
||||
@@ -245,7 +246,7 @@ class TextInput extends Component {
|
||||
}
|
||||
|
||||
_handleSelectionChange = (e) => {
|
||||
const { onSelectionChange, selection = {} } = this.props;
|
||||
const { onSelectionChange, selection = emptyObject } = this.props;
|
||||
if (onSelectionChange) {
|
||||
try {
|
||||
const node = e.target;
|
||||
|
||||
@@ -99,7 +99,7 @@ class View extends Component {
|
||||
onMagicTap,
|
||||
removeClippedSubviews,
|
||||
/* eslint-enable */
|
||||
...other
|
||||
...otherProps
|
||||
} = this.props;
|
||||
|
||||
const flattenedStyle = StyleSheet.flatten(style);
|
||||
@@ -107,27 +107,24 @@ class View extends Component {
|
||||
// 'View' needs to set 'flexShrink:0' only when there is no 'flex' or 'flexShrink' style provided
|
||||
const needsFlexReset = !flattenedStyle || (flattenedStyle.flex == null && flattenedStyle.flexShrink == null);
|
||||
|
||||
const normalizedEventHandlers = eventHandlerNames.reduce((handlerProps, handlerName) => {
|
||||
const component = this.context.isInAButtonView ? 'span' : 'div';
|
||||
|
||||
eventHandlerNames.reduce((props, handlerName) => {
|
||||
const handler = this.props[handlerName];
|
||||
if (typeof handler === 'function') {
|
||||
handlerProps[handlerName] = this._normalizeEventForHandler(handler, handlerName);
|
||||
props[handlerName] = this._normalizeEventForHandler(handler, handlerName);
|
||||
}
|
||||
return handlerProps;
|
||||
}, {});
|
||||
return props;
|
||||
}, otherProps);
|
||||
|
||||
const component = this.context.isInAButtonView ? 'span' : 'div';
|
||||
const props = {
|
||||
...other,
|
||||
...normalizedEventHandlers,
|
||||
style: [
|
||||
styles.initial,
|
||||
style,
|
||||
needsFlexReset && styles.flexReset,
|
||||
pointerEventsStyle
|
||||
]
|
||||
};
|
||||
otherProps.style = [
|
||||
styles.initial,
|
||||
style,
|
||||
needsFlexReset && styles.flexReset,
|
||||
pointerEventsStyle
|
||||
];
|
||||
|
||||
return createDOMElement(component, props);
|
||||
return createDOMElement(component, otherProps);
|
||||
}
|
||||
|
||||
_normalizeEventForHandler(handler, handlerName) {
|
||||
|
||||
@@ -105,6 +105,8 @@ var warning = require('fbjs/lib/warning');
|
||||
* this.props.onKeyboardDidHide
|
||||
*/
|
||||
|
||||
const emptyObject = {};
|
||||
|
||||
var IS_ANIMATING_TOUCH_START_THRESHOLD_MS = 16;
|
||||
|
||||
type State = {
|
||||
@@ -378,7 +380,7 @@ var ScrollResponderMixin = {
|
||||
if (typeof x === 'number') {
|
||||
console.warn('`scrollResponderScrollTo(x, y, animated)` is deprecated. Use `scrollResponderScrollTo({x: 5, y: 5, animated: true})` instead.');
|
||||
} else {
|
||||
({x, y, animated} = x || {});
|
||||
({x, y, animated} = x || emptyObject);
|
||||
}
|
||||
const node = this.scrollResponderGetScrollableNode()
|
||||
node.scrollLeft = x || 0
|
||||
|
||||
@@ -7,13 +7,15 @@
|
||||
|
||||
import emptyFunction from 'fbjs/lib/emptyFunction';
|
||||
|
||||
const emptyObject = {};
|
||||
|
||||
const applyLayout = (Component) => {
|
||||
const componentDidMount = Component.prototype.componentDidMount || emptyFunction;
|
||||
const componentDidUpdate = Component.prototype.componentDidUpdate || emptyFunction;
|
||||
|
||||
Component.prototype.componentDidMount = function () {
|
||||
componentDidMount.call(this);
|
||||
this._layoutState = {};
|
||||
this._layoutState = emptyObject;
|
||||
this._handleLayout();
|
||||
};
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import React from 'react';
|
||||
import StyleSheet from '../../apis/StyleSheet';
|
||||
|
||||
const emptyObject = {};
|
||||
|
||||
const roleComponents = {
|
||||
article: 'article',
|
||||
banner: 'header',
|
||||
@@ -17,7 +19,7 @@ const roleComponents = {
|
||||
region: 'section'
|
||||
};
|
||||
|
||||
const createDOMElement = (component, rnProps = {}) => {
|
||||
const createDOMElement = (component, rnProps = emptyObject) => {
|
||||
const {
|
||||
accessibilityLabel,
|
||||
accessibilityLiveRegion,
|
||||
@@ -25,15 +27,14 @@ const createDOMElement = (component, rnProps = {}) => {
|
||||
accessible = true,
|
||||
testID,
|
||||
type,
|
||||
...other
|
||||
...domProps
|
||||
} = rnProps;
|
||||
|
||||
const accessibilityComponent = accessibilityRole && roleComponents[accessibilityRole];
|
||||
const Component = accessibilityComponent || component;
|
||||
const domProps = {
|
||||
...other,
|
||||
...StyleSheet.resolve(other)
|
||||
};
|
||||
|
||||
Object.assign(domProps, StyleSheet.resolve(domProps));
|
||||
|
||||
if (!accessible) { domProps['aria-hidden'] = true; }
|
||||
if (accessibilityLabel) { domProps['aria-label'] = accessibilityLabel; }
|
||||
if (accessibilityLiveRegion) { domProps['aria-live'] = accessibilityLiveRegion; }
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
const emptyArray = [];
|
||||
|
||||
// Mobile Safari re-uses touch objects, so we copy the properties we want and normalize the identifier
|
||||
const normalizeTouches = (touches = []) => Array.prototype.slice.call(touches).map((touch) => {
|
||||
const normalizeTouches = (touches = emptyArray) => Array.prototype.slice.call(touches).map((touch) => {
|
||||
const identifier = touch.identifier > 20 ? (touch.identifier % 20) : touch.identifier;
|
||||
|
||||
const rect = touch.target && touch.target.getBoundingClientRect();
|
||||
@@ -59,21 +61,23 @@ function normalizeTouchEvent(nativeEvent) {
|
||||
}
|
||||
|
||||
function normalizeMouseEvent(nativeEvent) {
|
||||
const touches = [ {
|
||||
_normalized: true,
|
||||
clientX: nativeEvent.clientX,
|
||||
clientY: nativeEvent.clientY,
|
||||
force: nativeEvent.force,
|
||||
locationX: nativeEvent.clientX,
|
||||
locationY: nativeEvent.clientY,
|
||||
identifier: 0,
|
||||
pageX: nativeEvent.pageX,
|
||||
pageY: nativeEvent.pageY,
|
||||
screenX: nativeEvent.screenX,
|
||||
screenY: nativeEvent.screenY,
|
||||
target: nativeEvent.target,
|
||||
timestamp: Date.now()
|
||||
} ];
|
||||
const touches = [
|
||||
{
|
||||
_normalized: true,
|
||||
clientX: nativeEvent.clientX,
|
||||
clientY: nativeEvent.clientY,
|
||||
force: nativeEvent.force,
|
||||
locationX: nativeEvent.clientX,
|
||||
locationY: nativeEvent.clientY,
|
||||
identifier: 0,
|
||||
pageX: nativeEvent.pageX,
|
||||
pageY: nativeEvent.pageY,
|
||||
screenX: nativeEvent.screenX,
|
||||
screenY: nativeEvent.screenY,
|
||||
target: nativeEvent.target,
|
||||
timestamp: Date.now()
|
||||
}
|
||||
];
|
||||
return {
|
||||
_normalized: true,
|
||||
changedTouches: touches,
|
||||
@@ -87,7 +91,7 @@ function normalizeMouseEvent(nativeEvent) {
|
||||
stopPropagation: nativeEvent.stopPropagation.bind(nativeEvent),
|
||||
target: nativeEvent.target,
|
||||
timestamp: touches[0].timestamp,
|
||||
touches: (nativeEvent.type === 'mouseup') ? [] : touches
|
||||
touches: (nativeEvent.type === 'mouseup') ? emptyArray : touches
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user