mirror of
https://github.com/zhigang1992/react-native.git
synced 2026-04-28 12:15:37 +08:00
[React Native] Remove layout-only nodes
Summary: Remove layout-only views. Works by checking properties against a list of known properties that only affect layout. The `RCTShadowView` hierarchy still has a 1:1 correlation with the JS nodes. This works by adjusting the tags and indices in `manageChildren`. For example, if JS told us to insert tag 1 at index 0 and tag 1 is layout-only with children whose tags are 2 and 3, we adjust it so we insert tags 2 and 3 at indices 0 and 1. This keeps changes out of `RCTView` and `RCTScrollView`. In order to simplify this logic, view moves are now processed as view removals followed by additions. A move from index 0 to 1 is recorded as a removal of view at indices 0 and 1 and an insertion of tags 1 and 2 at indices 0 and 1. Of course, the remaining indices have to be offset to take account for this. The `collapsible` attribute is a bit of a hack to force `RCTScrollView` to always have one child. This was easier than rethinking out the logic there, but we could change this later. @public Test Plan: There are tests in `RCTUIManagerTests.m` that test the tag- and index-manipulation logic works. There are various scenarios including add-only, remove-only, and move. In addition, two scenario tests verify that the optimization works by checking the number of views and shadow views after various situations happen.
This commit is contained in:
@@ -367,8 +367,10 @@ static void RCTProcessMetaProps(const float metaProps[META_PROP_COUNT], float st
|
||||
- (NSString *)description
|
||||
{
|
||||
NSString *description = super.description;
|
||||
description = [[description substringToIndex:description.length - 1] stringByAppendingFormat:@"; viewName: %@; reactTag: %@; frame: %@>", self.viewName, self.reactTag, NSStringFromCGRect(self.frame)];
|
||||
return description;
|
||||
if (self.layoutOnly) {
|
||||
description = [@"* " stringByAppendingString:description];
|
||||
}
|
||||
return [[description substringToIndex:description.length - 1] stringByAppendingFormat:@"; viewName: %@; reactTag: %@; frame: %@>", self.viewName, self.reactTag, NSStringFromCGRect(self.frame)];
|
||||
}
|
||||
|
||||
- (void)addRecursiveDescriptionToString:(NSMutableString *)string atLevel:(NSUInteger)level
|
||||
@@ -392,6 +394,82 @@ static void RCTProcessMetaProps(const float metaProps[META_PROP_COUNT], float st
|
||||
return description;
|
||||
}
|
||||
|
||||
- (BOOL)isLayoutOnly
|
||||
{
|
||||
if (![self.viewName isEqualToString:@"RCTView"]) {
|
||||
// For now, only `RCTView`s can be layout-only.
|
||||
return NO;
|
||||
}
|
||||
|
||||
// dispatch_once is unnecessary because this property SHOULD only be accessed
|
||||
// on the shadow queue
|
||||
static NSSet *layoutKeys;
|
||||
if (!layoutKeys) {
|
||||
// Taken from LayoutPropTypes.js with the exception that borderWidth,
|
||||
// borderTopWidth, borderBottomWidth, borderLeftWidth, and borderRightWidth
|
||||
// were removed because black color is assumed
|
||||
static NSString *const keys[] = {
|
||||
@"width",
|
||||
@"height",
|
||||
@"top",
|
||||
@"left",
|
||||
@"right",
|
||||
@"bottom",
|
||||
@"margin",
|
||||
@"marginVertical",
|
||||
@"marginHorizontal",
|
||||
@"marginTop",
|
||||
@"marginBottom",
|
||||
@"marginLeft",
|
||||
@"marginRight",
|
||||
@"padding",
|
||||
@"paddingVertical",
|
||||
@"paddingHorizontal",
|
||||
@"paddingTop",
|
||||
@"paddingBottom",
|
||||
@"paddingLeft",
|
||||
@"paddingRight",
|
||||
@"position",
|
||||
@"flexDirection",
|
||||
@"flexWrap",
|
||||
@"justifyContent",
|
||||
@"alignItems",
|
||||
@"alignSelf",
|
||||
@"flex",
|
||||
|
||||
// Special case is handled below.
|
||||
@"collapsible",
|
||||
};
|
||||
layoutKeys = [NSSet setWithObjects:keys count:sizeof(keys)/sizeof(*keys)];
|
||||
}
|
||||
|
||||
NSNumber *collapsible = self.allProps[@"collapsible"];
|
||||
if (collapsible && !collapsible.boolValue) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
for (NSString *key in self.allProps) {
|
||||
if (![layoutKeys containsObject:key]) {
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (CGRect)adjustedFrame
|
||||
{
|
||||
CGRect frame = self.frame;
|
||||
RCTShadowView *superview = self;
|
||||
while ((superview = superview.superview) && superview.layoutOnly) {
|
||||
const CGRect superviewFrame = superview.frame;
|
||||
frame.origin.x += superviewFrame.origin.x;
|
||||
frame.origin.y += superviewFrame.origin.y;
|
||||
}
|
||||
|
||||
return frame;
|
||||
}
|
||||
|
||||
// Margin
|
||||
|
||||
#define RCT_MARGIN_PROPERTY(prop, metaProp) \
|
||||
|
||||
Reference in New Issue
Block a user