样式

每个组件类型都支持一组预定义的样式属性。ReactXP 为每个基础组件定义了强类型样式对象。这允许在编译时进行检查和提供 IntelliSense。样式必须使用提供的 RX.Styles 方法进行分配。这些方法还会对值进行验证并执行简单的平台或浏览器特定转换。以下是一些示例:

const myViewStyle = RX.Styles.createViewStyle({
    backgroundColor: 'green'
});

const myTextStyle = RX.Styles.createTextStyle({
    fontSize: 36,
    fontWeight: 'bold'
});

许多基础组件共享通用的样式属性子集。例如,几乎每个基础组件都支持 flexbox 属性。请参阅下文以了解一些常见的属性集。

组合样式

所有基础组件都支持一个 style 属性,该属性可以接受单个样式或样式数组(或嵌套数组)。如果提供了样式数组,则样式会以从左到右的深度优先方式进行组合。Falsy 值(false、null、undefined)也可以在样式数组中指定。这允许以下常见模式。

    let buttonTextStyles = [_styles.baseText, this.state.hovering && _styles.hoverText];

这是另一个实现相同功能的变体——稍微冗长一些,但可以说更容易阅读。

let buttonTextStyles = [_styles.baseText];
if (this.state.hovering) {
    buttonTextStyles.push(_styles.hoverText);
}

如果“margin”和“padding”属性与边缘特定属性(例如“marginLeft”或“paddingBottom”)组合,则特定属性总是会覆盖通用属性。这与 React Native 的组合行为相匹配(但与 CSS 不同)。

// this.props.style might be undefined, a single style, or a (potentially-nested)
// array of styles.
<RX.View style={ [_styles.defaultStyle, this.props.style] } />

样式缓存

默认情况下,ReactXP 分配的样式是缓存的。这使得调用者可以通过句柄引用样式,而不是每次使用时都重建完整的样式结构。对于依赖动态参数或在非静态代码路径中分配的样式,禁用缓存很重要。否则会导致内存泄漏。要禁用缓存,请将 false 指定为创建方法的第二个参数。

let dynamicViewStyle = RX.Styles.createViewStyle({
    backgroundColor: userColor
}, false);

样式文档约定

对于每个样式属性,都指定了类型和默认值。对于枚举值,枚举中的第一个项是默认值。

颜色值以字符串形式指定。它们可以指定为颜色名称(例如“red”)、三位或六位十六进制值(例如“#444”或“#ff00ee”),或 rgb 或 rgba 值(例如“rgb(255, 0, 67)”或“rgba(255, 0, 67, 0.5)”)。

Flexbox 样式属性

ReactXP 采用了 React Native 定义的简化 flexbox 规则和默认值。它在以下方面与 CSS 中的 flexbox 标准有所不同。

  • 默认情况下,所有组件都遵循 flex 规则(Text 是一个值得注意的例外)。与 CSS 不同,无需指定“display: flex”。

  • 宽度、高度和其他测量值都被假定为像素值。不支持其他单位(包括百分比)。

  • 虽然可以单独指定 flexGrow、flexShrink 和 flexBasis 值,但更常见的是使用名为“flex”的快捷方式来指定 flex 参数。它接受一个整数值,并涵盖以下常见情况。
    • “flex: 0”表示“flex: 0 0 auto”
    • “flex: n”(其中 n 为负数)表示“flex: 0 n auto”
    • “flex: p”(其中 p 为正数)表示“flex: p 1 auto”
  • 默认的 flexDirection 是“column”而不是“row”。

  • 所有元素的默认位置是“relative”而不是“auto”。

  • 按钮的默认 justifyContent 是“center”而不是“flex-start”。

容器布局

flex: number = 0;
alignSelf: 'auto' | 'flex-start' | 'flex-end' | 'center' | 'stretch';

子元素布局

alignContent: 'auto' | 'flex-start' | 'flex-end' | 'center' | 'stretch';
alignItems: 'stretch' | 'flex-start' | 'flex-end' | 'center';
flexWrap: 'wrap' | 'nowrap';
flexDirection: 'column' | 'row' | 'column-reverse' | 'row-reverse';
justifyContent: 'flex-start' | 'flex-end' | 'center' | 'space-between' |
    'space-around';

尺寸覆盖

height: number = undefined; // Can be animated
width: number = undefined; // Can be animated
maxHeight: number = undefined;
maxWidth: number = undefined;
minHeight: number = undefined;
minWidth: number = undefined;

位置覆盖

position: 'absolute' | 'relative';
top: number = undefined; // Can be animated
right: number = undefined; // Can be animated
bottom: number = undefined; // Can be animated
left: number = undefined; // Can be animated

外边距

margin: number; // Sets all four margin attributes
marginHorizontal: number; // Sets left and right
marginVertical: number; // Sets top and bottom
marginTop: number = 0;
marginRight: number = 0;
marginBottom: number = 0;
marginLeft: number = 0;

内边距

padding: number; // Sets all four padding attributes
paddingHorizontal: number; // Sets left and right
paddingVertical: number; // Sets top and bottom
paddingTop: number = 0;
paddingRight: number = 0;
paddingBottom: number = 0;
paddingLeft: number = 0;

视图样式属性

颜色与不透明度

backgroundColor: color = undefined; // Value is animatable
opacity: number = 1.0; // Value is animatable
acrylicOpacityUWP: number = 1.0; // UWP only
acrylicSourceUWP: 'host' | 'app'; // UWP only
acrylicTintColorUWP: string = undefined; // UWP only; default = backgroundColor

溢出

overflow: 'hidden' | 'visible';

边框

borderWidth: number;
borderTopWidth: number;
borderRightWidth: number;
borderBottomWidth: number;
borderLeftWidth: number;
borderColor: color;
borderStyle: 'solid' | 'dotted' | 'dashed' | 'none';
borderRadius: number;  // Sets all four border radius attributes; value is animatable
borderTopRightRadius: number = 0;
borderBottomRightRadius: number = 0;
borderBottomLeftRadius: number = 0;
borderTopLeftRadius: number = 0;

阴影

// NOTE: If applied to a Text element, these properties translate to text shadows,
// not a box shadow.
shadowOffset: { height: number; width: number } = { 0, 0 };
shadowRadius: number = 0;
shadowColor: color = 'black';
elevation: number; // Android only

杂项

wordBreak: 'break-all' | 'break-word'; // Web only
appRegion: 'drag' | 'no-drag'; // Web only
cursor: 'pointer' | 'default'; // Web only

变换样式属性

变换

transform: {
    // All transform values are animatable
    perspective: string = undefined;
    rotate: string = undefined;
    rotateX: string = undefined;
    rotateY: string = undefined;
    rotateZ: string = undefined;
    scale: number = 0;
    scaleX: number = 0;
    scaleY: number = 0;
    translateX: number = 0;
    translateY: number = 0;
}

文本样式属性

字体信息

// Attributes in this group cascade to child RX.Text components
fontFamily: string = undefined;
fontStyle: 'normal' | 'italic';
fontWeight: 'normal' | 'bold' | '100' | '200' | '300' | '400' | '500' |
    '600' | '700' | '800' | '900';
fontSize: number = undefined;

// Shortcut that sets all three font attributes
font: {
    fontFamily: string = undefined;
    fontStyle: 'normal' | 'italic';
    fontWeight: 'normal' | 'bold' | '100' | '200' | '300' | '400' | '500' |
        '600' | '700' | '800' | '900';
}

文本颜色

// Attributes in this group cascade to child RX.Text components
color: color = 'black'; // Value is animatable

间距覆盖

// Attributes in this group cascade to child RX.Text components
letterSpacing: number = 1;
lineHeight: number = 1;

对齐

textAlign: 'auto' | 'left' | 'right' | 'center' | 'justify';
textAlignVertical: 'auto' | 'top' | 'bottom' | 'center'; // Android specific

文本装饰

textDecorationLine: 'none' | 'underline' | 'line-through' |
    'underline line-through';
textDecorationStyle: 'solid' | 'double' | 'dotted' | 'dashed';
textDecorationColor: string = 'black';

书写方向

writingDirection?: 'auto' | 'ltr' | 'rtl';

杂项

includeFontPadding: boolean = true; // Android specific