React Native全局样式

119

我对React还比较陌生,但我理解基于组件和内联样式的好处。但我想知道是否有一种合适的方法来使用某种全局样式。例如,我希望在我的整个应用程序中都使用相同的文本和按钮颜色。

与其在每个组件中重复(后续需要更改时必须在多个位置进行更改),我最初想到的是创建一个“基础” StyleSheet 类,并将其导入到我的组件中。

是否有更好或更“React”的方法?

11个回答

151

您可以创建一个可重复使用的样式表。例如:

style.js

'use strict';
import { StyleSheet } from 'react-native';

module.exports = StyleSheet.create({
    alwaysred: {
        backgroundColor: 'red',
        height: 100,
        width: 100,
    },
});

在你的组件中:

const s = require('./style');

然后:

<View style={s.alwaysred} ></View>

25
现在你可以直接使用import { StyleSheet } from 'react-native'; - LYu
我已经添加了一个答案,解释了获取全局样式的另一种方法,你可能想要看一下https://dev59.com/R10Z5IYBdhLWcg3w-EXS#41751407。它更加灵活,并且符合React的精神,因为它避免了静态定义。 - Mr Br
我不同意,这不是DRY,也不是像React生态系统中推荐的基于组件的设计(或架构)。每个具有默认样式的组件都需要添加style={defaultStyle}。相反,您可以创建一个DefaultView并使用它来代替提供的已按您的规格进行了样式化的view。我之前写过一篇详细介绍这种方法的答案:https://dev59.com/R10Z5IYBdhLWcg3w-EXS#52429040 - ThaJay

107
创建一个用于样式的文件(例如,Style.js)。
以下是一个例子:
import { StyleSheet } from 'react-native';

export default StyleSheet.create({
  container: {
    flex: 1
  },
  welcome: {
    fontSize: 20
  }
});

在您想要使用自己样式的任何文件中,添加以下内容:

import styles from './Style'

3
"./Styles" 应该改为 "./Style",以匹配文件名 Style.js。 - oOEric

16

如果您只想设置一些全局变量,可以尝试。

AppStyles.js

export default AppStyles = {
    colour: {
        background: '#f4f9fd',
        font: '#434e5a',
        primary: '#ff3b30'
    }
}

index.ios.js

import AppStyles from './AppStyles';

const styles = StyleSheet.create({
    container: {
        backgroundColor: AppStyles.colour.background
    }
});

在AppStyles.js中不需要导入,但当您只想要一些简单的全局样式变量时,这非常完美! - willedanielsson
重复的答案stackoverflow.com/a/30858201/5243543 - ThaJay

10

您也可以尝试使用react-native-extended-stylesheet,它支持全局样式变量:

// app.js
EStyleSheet.build({
   buttonColor: 'green'
});

// component.js
var styles = EStyleSheet.create({
  button: {
    backgroundColor: '$buttonColor',
    ...
  }
});

我有一个问题,它不允许 CSS 智能感应工作。 - Hardik Shah

8

您需要创建一个文件来存储所有的样式,如 'styles.js',并按照您的需求编写CSS类型的代码。

'use strict';
import {StyleSheet} from 'react-native';

export default StyleSheet.create({

    container: {
        flex: 1,
        justifyContent: 'center',
        alignItems: 'center',
        backgroundColor: '#F5FCFF',
    },

    title: {
        fontSize: 10,
        color: '#000',
        backgroundColor: '#fff'
    },

    button: {
        fontSize: 12,
        color: '#000',
        backgroundColor: '#fff'
    }

});

现在你可以看到,可以使用全局样式。
import React, { Component } from 'react';
import { View, Button } from 'react-native';
import StyleSheet from './config/styles';

export default class App extends Component {

  render() {
    return (
      <View
        style={StyleSheet.container}>
        <Button
          style={StyleSheet.button}
          title="Go to Lucy's profile"
        />
      </View>
    );
  }
}

重复的答案 - ThaJay

2

2023年3月更新: 这篇文章是在Hooks出现之前写的。现在,这个代码示例看起来会像这样:

const style = {
  color   : 'MidnightBlue',
  fontSize: 14,
}

export default function CustomText (props) {
  // Because of UseMemo, render is cheap even with props.style
  // altough useMemo adds at a little overhead too.
  const mergedStyle = useMemo(() => {
    if (props.style) return {...style, ...props.style}
    else return style
  }, [props.style])

  return (
    <Text style={mergedStyle}>
      {props.children}
    </Text>
  )
}

所有这些方法都直接回答了问题,但就我而言,在像React这样的组件化设计系统中,这不是正确的做法。

我们可以从原子组件开始,然后一层层地堆叠和分组,直到最上层。以下文章可能会更清晰地阐述这种思路: http://atomicdesign.bradfrost.com/chapter-2/

在自然界中,原子元素结合在一起形成分子。这些分子可以进一步结合形成相对复杂的生物体。

如果您需要一个不存在的基础组件,则可以创建它。然后,您可以使用它来制作其他更具体的组件。例如:

// rerender is cheaper without style prop when
// the default style is an unchanged reference
// instead of a new object every time.
const style = {
  color   : 'MidnightBlue',
  fontSize: 14,
}

function getStyle (styleProp) {
  // styleProp is able to overwrite style
  if (styleProp) return {...style, ...styleProp}
  else return style
}

export default function CustomText (props) {
  return (
    <Text style={getStyle(props.style)}>
      {props.children}
    </Text>
  )
}

然后在所有地方使用CustomText代替Text。您也可以对Viewdivspan或其他任何内容进行相同的操作。


@TheJay,这对于单个组件来说是完全有意义的,但是如何将样式应用于所有屏幕呢?类似于asp.net主页面:https://www.quanzhanketang.com/aspnet/aspnet_masterpages.html - mxmissile
你读了最后一句话吗?只需在所有地方将 <Text /> 替换为 <CustomText /> 即可,这很容易。你甚至可以将 CustomText 导入为 Text,以便仅需替换导入即可。 - ThaJay

2

我使用类似的方法使我的工作正常。

创建一个名为“constants”的目录 在./constants/AppStyles.js中创建一个文件。

 /**
 * Project level stylesheet for common styles
 */


import { StyleSheet } from 'react-native';

export default StyleSheet.create({
  container: {
    flex: 1,
    margin: 20,
    alignItems: 'center',
    alignContent: 'center',
    paddingVertical: 60
  }
  
});

然后在 App.js 中引用此文件和创建的样式。
import React from 'react';
import {
  View,
  Text
} from 'react-native';
import AppStyles from './constants/AppStyles';

const App = () => {
  return (
    <View style={ AppStyles.container }>
      <Text>MOST BASIC Template EVER!</Text>
    </View>
  );
};

export default App;

我掉进的陷阱

  • 我在import {AppStyles} from './constants/AppStyles';周围加上了花括号 错误 :-(
  • 我将AppStyles创建为一个组件,并尝试导出一个常量 错误 :-)

在网上找到了一门好课程,从中弄明白了问题所在。


1
一个更好的解决方案是使用全局对象并创建一个单独的主题文件。
在根文件中导入该文件。
import theme from './theme'
global.theme = theme

然后,项目中任何位置的组件都可以按照以下方式使用它

<Text style={global.theme.text} > Stackoverflow Answer </Text>

这样,我们就不必一遍又一遍地导入主样式文件了。主题可以通过一个文件进行管理。


0

外部 CSS 文件 main.css

'use strict';

var {
   StyleSheet,
 } = 'react-native';

module.exports = StyleSheet.create({

  main: {
     backgroundColor: 'gray',
     height: 20,
     width: 100,
  }
});

在组件中创建CSS文件的实例。

var mainCss = require('./main');

<View style={mainCss.main}><Text>Hello</Text></View>

重复的答案stackoverflow.com/a/30858201/5243543 - ThaJay

0
在这里,您可以找到一种优雅的方式来排序您的样式,然后导入到不同的组件中。您可以创建一个文件夹,收集所有的样式文件,并创建一个 index.js,它将作为门面工作:
index.js会像这样:
import Variables from './variables';
import GlobalStyles from './global'; 

export { Variables, GlobalStyles };

然后像这样导入:

import { GlobalStyles } from './stylesheets/index';

更多信息请参见:

https://thoughtbot.com/blog/structure-for-styling-in-react-native


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接