本机反应-与普通对象相比,使用 StyleSheet 有什么好处?

与普通对象相比,使用 StyleSheet.create()到底有什么好处?

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

V.

const styles = {
container: {
flex: 1
}
}
18387 次浏览

直接引用反应本机 StyleSheet.js的评论部分

代码质量:

  • 通过将样式从呈现函数中移除,可以使代码更容易理解。

  • 命名样式是为呈现函数中的低级组件添加意义的一种好方法。

演出:

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

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

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

公认的答案不是 OP 问题的答案。

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

经过一些研究,我发现如下(请更新,如果你有任何信息)。 StyleSheet.create的优点应该是:

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

没有好处,就这样。

误区一: StyleSheet更有表现力

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

流言的起源可能是因为本地反应小组试图这样做,但他们没有成功。在官方文档中没有任何关于性能的内容: https://facebook.github.io/react-native/docs/stylesheet.html,而源代码声明“尚未实现”: https://github.com/facebook/react-native/blob/master/Libraries/StyleSheet/StyleSheet.js#L207

谬论2: StyleSheet在编译时验证样式对象

这是不正确的。普通的 JavaScript 不能在编译时验证对象。

两件事:

  • 它在运行时进行验证,但是当您将样式对象传递给组件时也进行验证。
  • 它确实会在编译时 如果您正在使用 Flow 或 TypeScript进行验证,但是当您将对象作为样式支持传递给组件时,或者如果您正确地按下面的方式键入对象时,也会进行验证。也没什么区别。
const containerStyle: ViewStyle = {
...
}

过去人们认为使用 StyleSheet 更有效率,因此 RN 团队一直使用 曾经是 建议直到版本0.57,但是现在不再推荐使用它,正如在 另一个答案中对这个问题所正确指出的那样。

注册护士文件现在推荐 StyleSheet 的原因如下,尽管我认为这些原因同样适用于在呈现函数之外创建的普通对象:

  • 通过将样式从呈现函数移开,可以使 代码更容易理解。
  • 命名样式是增加底层含义的好方法 渲染函数中的组件。

那么,我认为 在普通对象上使用 StyleSheet 的可能好处是什么呢?

1)尽管有相反的说法,我在 RN v0.59.10上的测试表明,当调用 StyleSheet.create()和类型脚本(可能是 flow)时,会得到一些验证,在编译时也会报告错误。即使没有编译时检查,我认为在运行时验证用于呈现的样式 之前仍然是有益的,特别是在使用这些样式的组件可以有条件地呈现的情况下。这将允许在不必测试所有呈现方案的情况下检测这些错误。

2)考虑到 RN 团队推荐的 StyleSheet,他们可能仍然希望在未来使用 StyleSheet来提高性能,他们可能还有其他可能的改进,例如:

3)当前的 StyleSheet.create()运行时验证是有用的,但有一点局限性。它似乎仅限于使用 flow 或类型脚本进行类型检查,因此会检测到比如 flex: "1"borderStyle: "rubbish",但不会检测到 width: "rubbish",因为它可能是一个百分比字符串。RN 团队可能在未来通过检查百分比字符串或范围限制来改进这种验证,或者您可以在自己的函数中包装 StyleSheet.create()来进行更广泛的验证。

4)通过使用 StyleSheet,你可能更容易转换到第三方的替代品/扩展,比如提供更多功能的 本机扩展样式表

除了在 TypeScript 中键入验证外,我没有发现 StyleSheet和普通对象之间有任何区别。

例如,this (注意输入差异) :

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,
},
};

通过 StyleSheet.create创建样式只有在全局变量 __DEV__设置为 true (或者在 Android 或 IOS 模拟器中运行时参见 反应本地 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;
}

我建议使用它,因为它在开发期间执行运行时验证,而且它会冻结对象。

因此,今天,在阅读了所有的答案和做了一些研究之后,我创建了一个关于使用 Stylesheet代替普通对象的总结。

  1. 基于 反应文件,当复杂性开始增加时,应该使用样式表。

样式道具可以是一个普通的旧 JavaScript 对象。 随着组件复杂性的增加,使用 StyleSheet.create 在一个地方定义多个样式通常会更简单。

  1. 在模拟器中,当使用样式表时将显示一个 错误,而当使用普通对象时将只显示一个 警告
  2. 基于项目2,看起来它在编译时有一些验证。(很多人说这是个神话)
  3. 如果将来需要为第三方库进行迁移,对于像 react-native-extended-stylesheet这样的第三方库,如果使用样式表,迁移会更容易。
  4. 你有一些 方法物业促进发展。例如,属性 StyleSheet.absoluteFill将执行 position: 'absolute', left: 0, right: 0, top: 0, bottom: 0,或者方法 compose()将允许您组合两种样式,并重写它。

附注: 性能回答看起来是个神话。

我的意见?

基于项目2和5,转到样式表而不是纯对象。

我知道这是一个非常晚的答案,但我已经看到,它显示您的错误,并提供自动完成编辑器时,您使用 StyleSheet