在React Native中使用CSS模块

2,565 阅读9分钟

在React Native应用中,有相当多的方法可以实现良好的造型。在本教程中,我们将回顾React Native中的传统样式设计方法,并向你介绍一种流行的替代方法。CSS模块。

由于React Native的强大功能,以及它支持开箱即用的本地HTML和CSS样式,设计和创建自定义移动应用程序的门槛相当低。如果你已经熟悉网页开发并有使用React的经验,那么你很幸运,因为这些技能将非常容易转化。

React本地风格与CSS模块

React Native中使用的核心布局设计系统是CSS Flexbox,这是在开发人员中最受欢迎的网页设计系统。有了Flexbox的强大功能,高级和初级的开发者都能很好地设计移动应用程序。

React Native应用程序通常使用内联样式或造型道具进行造型。CSS模块为使用传统的React Native样式提供了一个可移植的、更强大的替代方案。CSS模块使你能够在你的React Native应用中使用本地范围的样式,这使你的代码明显更干净,更容易阅读。

在本指南中,我们将通过实际例子展示每种方法是如何工作的,并证明为什么你应该考虑使用CSS模块来为你的React Native应用设计样式。

React Native中的样式设计。传统方法

React Native让你用JavaScript来设计整个应用的样式。每个组件都可以使用一个名为style 的道具,这使你可以为这些组件编写CSS样式。

React Native有两种创建样式的主要方法:内联样式和使用style 道具来样式子组件。从本质上讲,你有一个StyleSheet.create 方法来一次定义多个样式,就像CSS中的内联样式表一样。

下面是一个例子,说明内联样式在React Native中是如何工作的。

App.js 文件

import React from 'react';
import { View, Text, SafeAreaView } from 'react-native';

export default function App() {
  return (
    <>
      <SafeAreaView>
        <View
          style={{
            flexDirection: 'row',
            justifyContent: 'space-evenly',
            alignItems: 'center',
            backgroundColor: '#6804CD',
            width: '100%',
            height: 30,
          }}
        >
          <Text style={{ color: '#ffffff', fontWeight: 'bold' }}>Alpha</Text>
          <Text style={{ color: '#ffffff', fontWeight: 'bold' }}>Bravo</Text>
          <Text style={{ color: '#ffffff', fontWeight: 'bold' }}>Charlie</Text>
          <Text style={{ color: '#ffffff', fontWeight: 'bold' }}>Delta</Text>
          <Text style={{ color: '#ffffff', fontWeight: 'bold' }}>Echo</Text>
          <Text style={{ color: '#ffffff', fontWeight: 'bold' }}>Foxtrot</Text>
        </View>
      </SafeAreaView>
    </>
  );
}

内联样式对于快速的、小型的应用来说是很好的,也适用于你想测试一些代码而不需要做完整的实现的场景。然而,正如你所看到的,有很多重复的地方,而且代码没有遵守DRY原则。这种类型的代码不会有很好的扩展,因为有很多重复的东西可以用一个CSS类来代替。

因为内联CSS必须用驼峰语法来写,与传统的CSS样式不同,将普通的CSS样式转换为这种语法需要稍长的时间。你不能只是复制和粘贴代码。

此外,要使内联样式具有响应性是相当困难的,因为媒体查询根本不起作用。唯一的选择是创建某种业务逻辑来使其工作,或者完全使用另一种方法。

下面的例子显示了如何使用样式道具产生相同的结果。

App.js 文件。

import React from 'react';
import { StyleSheet, View, Text, SafeAreaView } from 'react-native';

export default function App() {
  return (
    <>
      <SafeAreaView>
        <View style={styles.container}>
          <Text style={styles.text}>Alpha</Text>
          <Text style={styles.text}>Bravo</Text>
          <Text style={styles.text}>Charlie</Text>
          <Text style={styles.text}>Delta</Text>
          <Text style={styles.text}>Echo</Text>
          <Text style={styles.text}>Foxtrot</Text>
        </View>
      </SafeAreaView>
    </>
  );
}

const styles = StyleSheet.create({
  container: {
    flexDirection: 'row',
    justifyContent: 'space-evenly',
    alignItems: 'center',
    backgroundColor: '#6804CD',
    width: '100%',
    height: 30,
  },
  text: {
    color: '#ffffff',
    fontWeight: 'bold',
  },
});

React Native StyleSheet方法是在React Native应用程序中实现CSS样式的默认方法。StyleSheets基本上是一种抽象,与传统的CSS StyleSheets非常相似。代码明显更容易阅读,添加类名可以确保代码保持干燥。

这种CSS-in-JS的方法相当流行,尽管社区中对JavaScript和CSS是否应该在同一个文件中存在争议。这通常被称为关注点分离,它规定你不应该将JavaScript和CSS混在一起;两者应该存在于各自的文件中。

下面是代码在应用程序中渲染时的样子。

React Native Styling Example

为什么你应该使用CSS模块

除了内联样式和使用样式道具之外,一个很好的选择是使用CSS模块。CSS模块非常棒,因为它可以让你拥有组件范围内的CSS,这些CSS具有高度的可移植性,并为所分配的组件进行本地化。你不再需要担心选择器名称之间的冲突,例如其他可能具有相同命名惯例的CSS文件中的ID和类。

默认情况下,CSS模块是本地范围的文件,因此不会与其他CSS文件发生冲突。有了CSS模块,这些文件是用纯CSS编写的,但在JavaScript中被转换为对象,从而使它们更健壮,更安全地集成。

普通CSS和CSS模块的唯一区别是文件扩展名。普通的CSS使用header.css ,而CSS模块则使用header.module.css 的命名惯例。

CSS模块。一个实际的例子

下面你会看到我们在内联样式和使用样式道具的例子中所使用的相同代码,但这次我们将使用CSS模块来为我们的React Native应用样式。

App.js 文件。

import React from 'react';
import { View, Text, SafeAreaView } from 'react-native';
import style from './App.module.css';

export default function App() {
  return (
    <>
      <SafeAreaView>
        <View style={style.container}>
          <Text style={style.text}>Alpha</Text>
          <Text style={style.text}>Bravo</Text>
          <Text style={style.text}>Charlie</Text>
          <Text style={style.text}>Delta</Text>
          <Text style={style.text}>Echo</Text>
          <Text style={style.text}>Foxtrot</Text>
        </View>
      </SafeAreaView>
    </>
  );
}

当使用CSS模块时,你可以看到代码看起来很干净。这个文件中没有CSS StyleSheet。相反,它必须被导入,这样可以保持代码的分离。每个元素都有一个样式类,它来自App.module.css 文件。现在每个文件的CSS都是本地化的,所以不应该有任何命名冲突。

App.module.css 文件。

.container {
  flex-flow: row;
  justify-content: space-evenly;
  align-items: center;
  background-color: '#6804CD';
  width: '100%';
  height: 30;
}

.text {
  color: '#ffffff';
  font-weight: bold;
}

App.module.css 文件内的代码是普通的CSS。它没有驼峰;它只是一个普通的CSS文件,所以你可以得到完整的、不加修饰的CSS的力量。这包括媒体查询、悬停事件,等等。如果你在另一个文件里有一些CSS,很容易就能复制并粘贴过来--不需要转换。

使用CSS模块设计一个React Native应用程序

让我们再深入一点,用CSS模块设计一个完整的React Native应用。

在你开始之前,确保你的开发环境已经设置好了。在本教程中,我们将使用Expo框架和平台来开发React Native应用。

先决条件。

设置一个React Native应用

我们将使用Expo CLI工具创建React Native前台。

以下库是必需的。

首先,为该项目创建一个文件夹,然后运行下面的命令。

npx expo-cli init frontend

选择一个空白模板,继续设置。

cdfrontend 文件夹,然后用你的BASH应用程序安装下面的依赖项。

>yarn add babel-plugin-react-native-classname-to-style babel-plugin-react-native-platform-specific-extensions react-native-css-transformer react-native-paper --dev

在你的代码编辑器中打开项目,用下面的代码替换你的babel.config.js 文件中的代码。

module.exports = function (api) {
  api.cache(true);
  return {
    presets: ['babel-preset-expo'],
    plugins: [
      'react-native-classname-to-style',
      ['react-native-platform-specific-extensions', { extensions: ['css'] }],
    ],
  };
};

接下来,在你的项目根目录下的metro.config.js ,添加以下内容(如果你还没有这个文件,就创建这个文件)。

const { getDefaultConfig } = require("metro-config");

module.exports = (async () => {
  const {
    resolver: { sourceExts }
  } = await getDefaultConfig();
  return {
    transformer: {
      babelTransformerPath: require.resolve("react-native-css-transformer")
    },
    resolver: {
      sourceExts: [...sourceExts, "css"]
    }
  };
})();

最后,将下面的代码添加到根目录下的app.json 文件中。

{
  "expo": {
    "packagerOpts": {
      "config": "metro.config.js",
      "sourceExts": ["js", "jsx", "css"]
    }
  }
}

设置完毕后,现在是时候运行下面的命令来启动服务器了。

yarn start

你应该看到链接和一个二维码来打开Expo CLI开发者工具。在浏览器窗口中打开它,然后选择一个设备或模拟器,让它运行。

设计前端

创建一个名为App.module.css 的文件,并把它放在根目录下。把下面的代码复制到相应的文件中,你应该看到一个使用React Native和CSS模块设计的非常酷的应用程序。

App.js

import React from 'react';
import { SafeAreaView, Text, View, ImageBackground, TouchableOpacity } from 'react-native';
import { Appbar } from 'react-native-paper';
import { Platform } from 'react-native';
import style from './App.module.css';

const MORE_ICON = Platform.OS === 'ios' ? 'dots-horizontal' : 'dots-vertical';

const image = {
  uri: 'https://images.unsplash.com/photo-1510414842594-a61c69b5ae57?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=2070&q=80',
};

export default function App() {
  return (
    <SafeAreaView>
      <Appbar.Header>
        <Appbar.Content title="Valkyrie Sky" subtitle={'The journey of a lifetime'} />
        <Appbar.Action icon="magnify" onPress={() => {}} />
        <Appbar.Action icon={MORE_ICON} onPress={() => {}} />
      </Appbar.Header>
      <View style={style.container}>
        <ImageBackground source={image} resizeMode="cover" style={style.appbg}>
          <View style={style.main}>
            <View>
              <Text style={style.mainheading}>McWay Falls, United States</Text>
            </View>
            <View style={style.location}>
              <Text>⭐ 5.0</Text>
              <Text style={style.locationicons}>🕜 7 Hours</Text>
              <Text>✈ 200 km</Text>
            </View>
            <View style={style.booking}>
              <View style={style.party}>
                <TouchableOpacity style={style.partybtn}>
                  <Text>-</Text>
                </TouchableOpacity>
                <Text>5</Text>
                <TouchableOpacity style={style.partybtn}>
                  <Text>+</Text>
                </TouchableOpacity>
              </View>
              <View>
                <Text>🕗 5 Days</Text>
              </View>
            </View>
          </View>
          <View style={style.content}>
            <View style={style.contentheading}>
              <Text style={style.selected}>Descriptions</Text>
              <Text style={style.unselected}>Facility</Text>
            </View>
            <View>
              <Text style={style.description}>
                McWay Falls is an 80-foot-tall waterfall on the coast of Big Sur in central California that flows
                year-round from McWay Creek in Julia Pfeiffer Burns State Park, about 37 miles south of Carmel, into the
                Pacific Ocean.
              </Text>
            </View>
          </View>
          <View style={style.book}>
            <Text style={style.bookcost}>$450</Text>
            <TouchableOpacity style={style.bookbtn}>
              <Text style={style.bookbtntext}>Book a Tour</Text>
            </TouchableOpacity>
          </View>
        </ImageBackground>
      </View>
    </SafeAreaView>
  );
}

这是一个相当简单的设计。里面有文本、按钮和图像元素。在顶部还有一个应用栏,它是用react-native-paper包创建的。这只是为了演示而设计的,没有任何功能。

App.module.css

.container {
  background-color: rgb(44, 0, 95);
  width: 100%;
  height: 100%;
}

.appbg {
  height: 100%;
  width: 100%;
}

.main {
  position: absolute;
  bottom: 0;
  background: rgb(242, 231, 255);
  width: 100%;
  height: 70%;
  border-radius: 30px;
  padding: 30px;
}

.mainheading {
  font-size: 20px;
  font-weight: bold;
  color: rgb(22, 22, 22);
}

.location,
.booking {
  display: flex;
  flex-flow: row nowrap;
  justify-content: flex-start;
  align-items: center;
  margin-top: 20;
  margin-bottom: 20;
}

.locationicons {
  margin-left: 20;
  margin-right: 20;
}

.party {
  display: flex;
  flex-flow: row nowrap;
  justify-content: space-evenly;
  align-items: center;
  background: rgb(208, 166, 255);
  border-radius: 30px;
  width: 100px;
  padding: 5px;
  margin-right: 20px;
}

.partybtn {
  background: rgb(183, 149, 221);
  padding: 5px;
  border-radius: 5px;
}

.content {
  background: #ffffff;
  width: 100%;
  position: absolute;
  bottom: 80;
  height: 300px;
  border-radius: 30px;
  padding: 30px;
}

.contentheading {
  display: flex;
  flex-flow: row nowrap;
  justify-content: space-evenly;
  margin-bottom: 20px;
}

.selected {
  color: rgb(84, 0, 105);
  font-weight: bold;
  font-size: 18px;
}

.unselected {
  font-weight: bold;
  font-size: 18px;
  color: rgb(133, 125, 125);
}

.description {
  line-height: 25px;
  color: rgb(133, 125, 125);
}

.book {
  position: absolute;
  bottom: 78;
  display: flex;
  flex-flow: row nowrap;
  justify-content: space-between;
  padding: 30px;
  background: rgb(44, 1, 114);
  width: 100%;
  border-radius: 30px;
  height: 90px;
}

.bookcost {
  color: #ffffff;
  font-size: 20px;
  font-weight: bold;
}

.bookbtn {
  background: #ffffff;
  border-radius: 10px;
  padding: 7px;
  height: 30px;
}

.bookbtntext {
  color: rgb(44, 1, 114);
  font-weight: bold;
}

这里有相当多的CSS样式。它们被适当地命名,所以应该很容易理解它们在代码中的位置以及它们的作用。

请看下面的最终设计。

Styling a React Native App Using CSS Modules

结论

正如你所看到的,在React Native应用程序中使用CSS模块是非常简单的。这是一个相当简单的例子;当然,当你有多个文件都有组件时,CSS模块的真正力量就会显现出来。创建本地范围的样式将大大改善你代码库的可读性和清晰度。

The postUsing CSS Modules in React Nativeappeared first onLogRocket Blog.