React Native-使用StyleSheet与普通对象相比有什么好处?


105

StyleSheet.create()与普通对象相比,使用它的好处是什么?

const styles = StyleSheet.create({
  container: {
    flex: 1
  }
}

VS.

const styles = {
  container: {
    flex: 1
  }
}

我获得了属性的VSCode智能感知支持。那是好处。
helloworld

Answers:


42

直接从React native 的StyleSheet.js的注释部分引用

代码质量:

  • 通过将样式从渲染功能中移开,可以使代码更易于理解。

  • 命名样式是一种在渲染函数中为低级组件添加含义的好方法。

性能:

  • 使用样式对象制作样式表可以通过ID引用它,而不必每次都创建一个新的样式对象。

  • 它还允许仅通过桥发送一次样式。所有后续使用都将引用一个ID(尚未实现)。

StyleSheet还将验证您的样式表内容。因此,样式属性不正确的任何错误都会在编译时显示,而不是在实际实现StyleSheet时在运行时显示。


46
前三个要点与OP的将样式对象声明为render函数之外的const的技术无关。
Owen Masback

12
当我阅读说明时,仍然看不到StyleSheet.create({styles...})比更好/更快{styles...}。代码很干净,您也使用命名而不是内联。任何人都可以阐明它吗?
freeall

9
StyleSheet在编译时提供验证
Jeevan Takhar

10
不赞成投票。不要在答案中添加无关的信息(“通过将样式从渲染功能中移开”等)。
罗伊森(Roymunson)'18

5
毫无疑问,OP的问题是StyleSheet.create与普通对象之间的区别,而不是课堂之外的内联与const 之间的区别
quirimmo '18

56

没有好处。期。

误区1:StyleSheet表现更好

与在StyleSheet外部声明的对象之间绝对没有性能差异render(如果render每次都在内部创建一个新对象,这将有所不同)。性能差异是一个神话。

神话的起源很可能是因为React Native团队试图做到这一点,但他们没有成功。在官方文档中找不到任何有关性能的信息:https : //facebook.github.io/react-native/docs/stylesheet.html,而源代码指出“尚未实现”:https : //github.com/ facebook / react-native / blob / master / Libraries / StyleSheet / StyleSheet.js#L207

误区二:StyleSheet在编译时验证样式对象

这不是真的。纯JavaScript无法在编译时验证对象。

两件事情:

  • 它会在运行时进行验证,但是当您将样式对象传递给组件时也会进行验证。没有不同。
  • 如果您使用Flow或TypeScript,它将在编译时进行验证,但是,一旦将对象作为样式道具传递给组件,或者是否正确键入了如下所示的对象,它也会进行验证。也没有区别。
const containerStyle: ViewStyle = {
   ...
}

3
真正。可能是由于文档的早期版本引起混淆,这意味着他们最终将通过id来引用样式。0.59文档中未提及该内容。
eremzeit

1
THX解谜。但是问题是开放的-为了什么?
Vasiliy Vanchuk


感谢您的回答。它值得更多投票:)
ThaJay

3
我的测试表明,它确实在运行时进行了验证,而无需传递给组件,例如,StyleSheet.create( {x:{flex: "1"}} )将在运行时失败,而打字稿会在编译时对其进行检查。
格伦·劳伦斯

24

接受的答案不是OP问题的答案。

问题不是内联样式和const类外部的区别,而是为什么我们应该使用StyleSheet.create而不是普通对象。

经过一番研究,我发现以下内容(如果有任何信息,请更新)。的优点StyleSheet.create应为以下内容:

  1. 验证样式
  2. 性能更好,因为它创建了样式到ID的映射,然后用该ID引用内部,而不是每次都创建一个新对象。因此,甚至更新设备的过程也更快,因为您不必每次都发送所有新对象。

11
这些都是神话。检查我的答案。
NikolaMihajlović19年

如果我在类之外(甚至作为类属性)定义样式对象,则将创建一次(或每个实例一次)。再次创建的相同对象仅在内部函数中相关。
ThaJay

是的const,但是没有class属性。静态类属性是。
quirimmo

5

它曾经被认为是使用样式表是更好的性能,并且 推荐为此由RN队,直到0.57版本,但它现在已不再推荐作为正确地指出另一个答案这个问题。

RN文档现在建议样式表如下原因,但我认为这些理由同样适用于所创建的渲染功能之外的普通对象:

  • 通过将样式从渲染功能中移开,可以使代码更易于理解。
  • 命名样式是一种在渲染函数中为低级组件添加含义的好方法。

所以,我觉得什么使用样式表在普通对象可能带来的好处?

1)尽管有相反的说法,但我在RN v0.59.10上的测试表明您在调用时确实得到了一些验证,StyleSheet.create()而打字稿(可能还有流程)也将在编译时报告错误。即使没有编译时间检查,我认为在将样式用于渲染之前进行样式的运行时验证仍然是有益的,尤其是在可以有条件地渲染使用这些样式的组件的情况下。这将允许拾取这些错误,而不必测试所有渲染方案。

2)鉴于样式表由RN小组建议,他们可能仍然有使用样式表来改善未来业绩的希望,他们可能在考虑到其他可能的改进,以及,例如:

3)当前的StyleSheet.create()运行时验证很有用,但有一定的局限性。它似乎仅限于使用流或打字稿进行类型检查,因此将选择say flex: "1"borderStyle: "rubbish",但不是,width: "rubbish"因为那可能是百分比字符串。RN团队将来可能会通过检查百分比字符串或范围限制之类的东西来改进此类验证,或者您可以包装StyleSheet.create()自己的函数来进行更广泛的验证。

4)通过使用StyleSheet,您也许可以更轻松地过渡到提供更多功能的第三方替代/扩展,例如react-native-extended-stylesheet


1

StyleSheet.create仅当将全局变量__DEV__设置为true时(或在Android或IOS仿真器中运行时,请参见React Native DEV和PROD变量),才能通过创建样式通过验证。

函数代码非常简单:

create < +S: ____Styles_Internal > (obj: S): $ReadOnly < S > {
  // TODO: This should return S as the return type. But first,
  // we need to codemod all the callsites that are typing this
  // return value as a number (even though it was opaque).
  if (__DEV__) {
    for (const key in obj) {
      StyleSheetValidation.validateStyle(key, obj);
      if (obj[key]) {
        Object.freeze(obj[key]);
      }
    }
  }
  return obj;
}

我建议使用它,因为它在开发过程中执行运行时验证,并且还会冻结对象。


0

StyleSheet除了在TypeScript中进行类型验证外,我和普通对象之间没有发现任何差异。

例如,这(注意键入差异):

import { View, Text, Image, StyleSheet } from 'react-native';
import logo from './logo.svg';

export default class App extends Component {
  render() {
    return (
      <View style={styles.someViewStyle}>
        <Text style={styles.someTextStyle}>Text Here</Text>
        <Image style={styles.someImageStyle} source={logo} />
      </View>
    );
  }
}

const styles: StyleSheet.create({
  someViewStyle: {
    backgroundColor: '#FFF',
    padding: 10,
  },
  someTextStyle: {
    fontSize: 24,
    fontWeight: '600',
  },
  someImageStyle: {
    height: 50,
    width: 100,
  },
});

等于这样:

import { View, Text, Image, ViewStyle, TextStyle, ImageStyle } from 'react-native';
import logo from './logo.svg';

export default class App extends Component {
  render() {
    return (
      <View style={styles.someViewStyle}>
        <Text style={styles.someTextStyle}>Text Here</Text>
        <Image style={styles.someImageStyle} source={logo} />
      </View>
    );
  }
}

const styles: {
  someViewStyle: ViewStyle;
  someTextStyle: TextStyle;
  someImageStyle: ImageStyle;
} = {
  someViewStyle: {
    backgroundColor: '#FFF',
    padding: 10,
  },
  someTextStyle: {
    fontSize: 24,
    fontWeight: '600',
  },
  someImageStyle: {
    height: 50,
    width: 100,
  },
};
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.