Create React App 学习-6.添加样式

1,732 阅读8分钟

添加样式

该项目设置使用webpack处理所有资产。webpack提供了一种自定义方式来“扩展” importJavaScript以外的概念。要表示JavaScript文件依赖于CSS文件,您需要从JavaScript文件导入CSS:

Button.css

.Button {
    padding:20px;
}

Button.js

import React,{Component} from "react";
import "./Button.css";//告知webpack该js文件需要使用Button.css样式
class Button extends Component{
    render(){
        return <div classNmae="Button"/>
    };
}

这不是React所必需的,但是许多人发现此功能很方便。您可以在此处了解这种方法的好处。但是,您应该意识到,这使您的代码比Webpack更加难以移植到其他构建工具和环境中。

在开发中,以这种方式表达依赖关系允许您在编辑样式时即时重新加载样式。在生产中,所有CSS文件都将.css在构建输出中串联到一个缩小的文件中。

如果您担心使用特定于Webpack的语义,则可以将所有CSS正确放入src/index.css。它仍然会从src/index.js中导入,但是如果以后迁移到其他构建工具,则可以始终删除该导入。

添加CSS模块样式表

注意:此功能可用于react-scripts@2.0.0或者更高版本

项目通过文件命名[name].module.css来支持CSS Modules。CSS模块通过自动创建格式为[filename]-[classname]--[hash]的唯一类名来对CSS进行返回界定。

提示: 如果要使用Sass预处理样式表,请确保遵循安装说明,然后按如下所示更改样式表文件扩展名:

[name].module.scss或[name].module.sass

CSS模块使您可以在不同文件中使用相同的CSS类名称,而不必担心命名冲突。

Button2.module.css

.error{
    background-color:red;
}

another-stylesheet.css

.error{
    color:red;
}

Button.js

import React,{Component} from "react";
import styles from './Button2.module.css';//引入css模块样式表作为样式
import "./another-stylesheet.css";//引入常规样式
class Button extends Component{
    render(){
        return (<div className={styles.error}>Error</div>);
    };
}
//style.error会转译成Button2_error_hash值这样一个类名

style.error会转译成Button2_error_hash值这样一个类名。 这样产生的最终结果是此按钮具有红色背景,但没有红色文本。

这是一个可选项。****标签完全支持常规样式表和CSS文件。对于以.module.css扩展名,将打开CSS模块。

添加Sass样式表

注意,此功能可用于react-script@2.0.0或更高版本。

通常,建议不要在不同组件之间重用相同的CSS类。例如,不要在<AcceptButton><RejectButton>组件中使用CSS类.Button,而建议创建一个具有自己的.Button样式的<Button>组件,该样式既可以渲染<AcceptButton>又可以渲染<RejectButton>(但不能继承)。

遵循此规则通常会使CSS预处理器的用处不大,因为诸如mixins和nesting之类的功能已被组件组成所取代。但是,如果发现CSS预处理程序很有价值,则可以对其进行集成。

要使用Sass,请先安装node-sass:

npm install node-sass --save
yarn add node-sass

现在你可以重命名src/App.csssrc/App.scss,然后更新src/App.js的import为src/App.scss

如果引入的是以.scss.sass结尾的任何文件都会被自动编译的。

要在Sass文件中共享变量,可以使用Sass imports。如src/App.scss和其他的组件样式文件可以引入包含共享变量的@import "./shared.scss"

@import "styles/_colors.scss";//假设src/下有一个styles文件夹
@import "~nprogress/nprogress";//从nprogress node module中引入css文件

要从node_modules中引入你必须用前缀~

node-sass也支持SASS_PATH变量

要使用相对于指定路径的import,要使引入node_modules的无需添加~前缀,你可以在项目根目录下新增一个.env文件,内容为SASS_PATH=node_modules:src。这样就可以如下引入了:

@import 'styles/colors';//
@import 'nprogress/nprogress';

对于windows系统,可以使用:

SASS_PATH=./node_modules;./src

注意:如果您使用的是Flow,请在您的模块中覆盖module.file_ext设置,.flowconfig使其能够识别.sass或归档.scss。您还需要包括module.file_ext的默认设置.js,.jsx,.mjs和.json文件。

添加CSS重置

此项目设置使用 PostCSS Normalize新增CSS Reset。

要开始使用它,请@import-normalize;在CSS文件中的任意位置添加。您只需添加一次即可,重复导入将自动删除。由于您只需要包含一次,因此添加它的好地方是index.css或App.css。

index.css

@import-normalize;//引入normalize.css样式
/*应用其他样式*/

您可以通过项目的browserslist控制使用normalize.css的哪些部分。

当browserslist是last 3 versions:

/**
 * Add the correct display in IE 9-.
 */
audio,
video {
  display: inline-block;
}
/**
 * Remove the border on images inside links in IE 10-.
 */
img {
  border-style: none;
}

当browserslist is last 2 versions:

/**
 * Remove the border on images inside links in IE 10-.
 */
img {
  border-style: none;
}

浏览器支持

浏览器的支持取决于normalize.css的支持

  • Chrome (last 3)
  • Edge (last 3)
  • Firefox (last 3)
  • Opera (last 3)
  • Safari (last 3)
  • Firefox ESR
  • iOS Safari (last 2)
  • Internet Explorer 9+

Post-Processing CSS

此项目设置会最小化您的CSS,并通过Autoprefixer自动向其添加供应商前缀,因此您无需担心。

对新的CSS功能(如allproperty,breakproperties,custom属性和media查询范围)的支持会自动填充,以添加对较旧浏览器的支持。

您可以通过在package.json中根据Browserslist规范调整browserslist键来自定义目标支持浏览器。

例如:

.App{
    display:flex;
    flex-direction:row;
    align-items:center;
}

变成:

.App {
  display: -webkit-box;
  display: -ms-flexbox;
  display: flex;
  -webkit-box-orient: horizontal;
  -webkit-box-direction: normal;
  -ms-flex-direction: row;
  flex-direction: row;
  -webkit-box-align: center;
  -ms-flex-align: center;
  align-items: center;
}

如果出于某种原因需要禁用自动前缀功能,请遵循本节。

默认情况下,“ CSS网格布局”前缀是禁用的,但不会删除手动前缀。如果您想加入CSS Grid前缀,请先熟悉一下它的局限性。

要启用CSS网格前缀,请添加/* autoprefixer grid: autoplace */到CSS文件的顶部。

添加图像,字体和文件

在使用webpack下,使用静态资源(例如图像和字体)的工作方式与CSS相似。

你可以直接在JavaScript模块中import 文件。这告诉webpack该文件将会包含在bundle文件中。与CSS导入不同,导入文件会为您提供一个字符串值。该值是您可以在代码中引用的最终路径,例如,作为src图像的属性或hrefPDF链接的。

为了减少对服务器的请求数量,导入小于10,000字节的图像将返回数据URI,而不是路径。这适用于以下文件扩展名:bmp,gif,jpg,jpeg和png。由于#1153, SVG文件被排除在外。您可以通过设置高级配置中IMAGE_INLINE_SIZE_LIMIT记录的环境变量来控制10,000字节的阈值。

import React from 'react';
import logo from './logo.png'; // Tell webpack this JS file uses this image
console.log(logo); // /logo.84287d09.png
function Header() {
  // Import result is the URL of your image
  return <img src={logo} alt="Logo" />;
}
export default Header;

这样可以确保在构建项目时,webpack可以将图像正确移动到build文件夹中,并为我们提供正确的路径。

这也适用于CSS:

.Logo {
  background-image: url(./logo.png);
}

webpack在CSS中找到所有相关的模块引用(以开头./),并将其替换为编译包中的最终路径。如果输入错误或意外删除了重要文件,则将看到编译错误,就像导入不存在的JavaScript模块时一样。webpack从内容哈希值生成已编译捆绑包中的最终文件名。如果文件内容将来会更改,则webpack将在生产中为其使用其他名称,因此您无需担心资产的长期缓存。

请注意,这也是webpack的自定义功能。

它不是React所必需的,但很多人喜欢它(React Native对图像使用类似的机制)。

下一节将介绍处理静态资产的另一种方法。

添加SVG

注意:此功能可用于react-script@2.0.0,更高版本react@16.3.0和更高版本。

上一节中介绍了添加SVG文件的一种方法。您也可以直接将SVG作为React组件导入。您可以使用两种方法之一。在您的代码中,它看起来像这样:

import { ReactComponent as Logo } from './logo.svg';
function App() {
  return (
    <div>
      {/* Logo is an actual React component */}
      <Logo />
    </div>
  );
}

如果您不想将SVG作为单独的文件加载,这将很方便。不要忘记import中的花括号!该ReactComponent 引入的名字告诉Create React App你想要一个render为SVG的React组件,而不是它的文件名。

提示:引入的SVG React组件接受一个title属性和一个svg元素可以接受的属性。使用该属性可以给svg组件添加一个可访问的标题。

加载.graphql文件

要加载.gql和.graphql文件,请首先通过运行以下命令安装graphql和graphql.macro软件包:

npm install --save graphql graphql.macro

或者使用yarn:

yarn add graphql graphql.macro

现在,无论何时你想要加载.gql或.graphql文件,从macro包中引入loader:

import {loader} from "graphql.macro";
const query = loader("./foo.graphql");

结果将自动包含,这意味着,如果上述文件foo.graphql包含以下内容:

query{
    hello{
        world
    }
}

前面的示例会变成:

const query = {
  'kind': 'Document',
  'definitions': [{
    ...
  }],
  'loc': {
    ...
    'source': {
      'body': '\\\\n  query {\\\\n    hello {\\\\n      world\\\\n    }\\\\n  }\\\\n',
      'name': 'GraphQL request',
      ...
    }
  }
};

你也可以使用gql模板标记就像使用graphql-tag包中的non-macro版本一样

import { gql } from 'graphql.macro';
 
const query = gql`
  query User {
    user(id: 5) {
      lastName
      ...UserEntry1
    }
  }
`;