CSS Modules 解决 react 项目 css 样式互相影响的问题 3年前

CSS Modules 解决 react 项目 css 样式互相影响的问题

CSS Modules 解决 react 项目 css 样式互相影响的问题

CSS Modules 解决 react 项目 css 样式互相影响的问题

1. CSS Modules引入目的

  写过CSS的人,应该都对一大长串选择器选中一个元素不陌生吧,这种方式,其实定义的就是全局样式,我们时常会因为选择器权重问题,没有把我们想要的样式加上去。

  另外,每次都需要把所有的样式表都导入到程序中,如果我们可以像使用js模块一样,想用哪块就用哪块,是不是就很理想了。

  CSS Modules就解决了这个问题,它自动为每一个类生成一个哈希值,可以惟一标志这个类,因此避免了我们说的第一个问题,它让我们可以像使用js模块那样,想用哪部分样式,就引入哪部分样式。下面我们来具体介绍它的使用方法。

2.CSS Modules使用方法

1) 如何在开启CSS Modules

  create-react-app 脚手架 引入 css-modules

modules:true,
localIdentName:'\[name\]\_\_\[local\]\_\_\[hash:base64:5\]'

  webpack.config.dev.js

{
  test: /.less$/,
  exclude: /node\_modules|antd.css/,
  use: \[
    require.resolve('style-loader'),
    {
      loader: require.resolve('css-loader'),
      options: {
        importLoaders: 1,
        modules:true,
        localIdentName:'\[name\]\_\_\[local\]\_\_\[hash:base64:5\]'
      },
    },
    {
      loader: require.resolve('postcss-loader'),
      options: {
        // Necessary for external CSS imports to work
        // https://github.com/facebookincubator/create-react-app/issues/2677
        ident: 'postcss',
        plugins: () => \[
          require('postcss-flexbugs-fixes'),
          autoprefixer({
            browsers: \[
              '>1%',
              'last 4 versions',
              'Firefox ESR',
              'not ie < 9', // React doesn't support IE8 anyway
            \],
            flexbox: 'no-2009',
          }),
        \],
      },
    },
    {
      loader: require.resolve('less-loader') // compiles Less to CSS
    }
  \],
},
{
  test: /.css$/,
  use: \[
    require.resolve('style-loader'),
    {
      loader: require.resolve('css-loader'),
      options: {
        importLoaders: 1,
      },
    },
    {
      loader: require.resolve('postcss-loader'),
      options: {
        // Necessary for external CSS imports to work
        // https://github.com/facebookincubator/create-react-app/issues/2677
        ident: 'postcss',
        plugins: () => \[
          require('postcss-flexbugs-fixes'),
          autoprefixer({
            browsers: \[
              '>1%',
              'last 4 versions',
              'Firefox ESR',
              'not ie < 9', // React doesn't support IE8 anyway
            \],
            flexbox: 'no-2009',
          }),
        \],
      },
    },
  \],
},

CSS Modules 解决 react 项目 css 样式互相影响的问题

  webpack.config.prod.js

{
  test: /.less$/,
  exclude: /node\_modules|antd.css/,
  loader: ExtractTextPlugin.extract(
    Object.assign(
      {
        fallback: {
          loader: require.resolve('style-loader'),
          options: {
            hmr: false,
          },
        },
        use: \[
          {
            loader: require.resolve('css-loader'),
            options: {
              importLoaders: 1,
              modules:true,
              localIdentName:'\[name\]\_\_\[local\]\_\_\[hash:base64:5\]',
              minimize: true,
              sourceMap: shouldUseSourceMap,
            },
          },
          {
            loader: require.resolve('postcss-loader'),
            options: {
              // Necessary for external CSS imports to work
              // https://github.com/facebookincubator/create-react-app/issues/2677
              ident: 'postcss',
              plugins: () => \[
                require('postcss-flexbugs-fixes'),
                autoprefixer({
                  browsers: \[
                    '>1%',
                    'last 4 versions',
                    'Firefox ESR',
                    'not ie < 9', // React doesn't support IE8 anyway
                  \],
                  flexbox: 'no-2009',
                }),
              \],
            },
          },
          {
            loader: require.resolve('less-loader') // compiles Less to CSS
          }
        \],
      },
      extractTextPluginOptions
    )
  ),
  // Note: this won't work without \`new ExtractTextPlugin()\` in \`plugins\`.
},
{
  test: /.css$/,
  loader: ExtractTextPlugin.extract(
    Object.assign(
      {
        fallback: {
          loader: require.resolve('style-loader'),
          options: {
            hmr: false,
          },
        },
        use: \[
          {
            loader: require.resolve('css-loader'),
            options: {
              importLoaders: 1,
              minimize: true,
              sourceMap: shouldUseSourceMap,
            },
          },
          {
            loader: require.resolve('postcss-loader'),
            options: {
              // Necessary for external CSS imports to work
              // https://github.com/facebookincubator/create-react-app/issues/2677
              ident: 'postcss',
              plugins: () => \[
                require('postcss-flexbugs-fixes'),
                autoprefixer({
                  browsers: \[
                    '>1%',
                    'last 4 versions',
                    'Firefox ESR',
                    'not ie < 9', // React doesn't support IE8 anyway
                  \],
                  flexbox: 'no-2009',
                }),
              \],
            },
          },
        \],
      },
      extractTextPluginOptions
    )
  ),
  // Note: this won't work without \`new ExtractTextPlugin()\` in \`plugins\`.
},

CSS Modules 解决 react 项目 css 样式互相影响的问题

2)CSS Modules用法

 1.基本使用方法

  在你的项目中,添加一个CSS文件,然后你就可以像引入js模块一样,在你的js文件中引入这个文件存放到一个对象中。这个对象中是一个包含连个属性的对象,其值就是自动生成的类名。这个类名也会替换页面中的类名。

style.scss

/\* style.scss \*/
.bgRed {
    background-color: #f00;
}

app/app.js

/\* app/app.js \*/

import React, {Component} from 'react';
import ReactDOM from 'react-dom';
/\* 引入我们定义的.scss文件 \*/
import styles from '../style/style.scss';

/\* 使用无状态函数定义我们的组件\*/
function Title() {
    console.log(styles);
    /\* 打印引入的styles,是一个包含连个属性的对象,其值就是自动生成的类名
        Object {white: "\_24PAw-tvdzL8pt4nyAvnJX", bgRed: "\_2R9YNZv7rx\_o02FHxKTBzC"}
     \*/
    return (
        /\* 在组件中引用 \*/
        <h1 className={styles.bgRed}>Hello React!</h1>
    );
}

/\* 渲染到页面中 \*/
ReactDOM.render(<Title />, document.body );

 最终页面结构,如下图所示:

CSS Modules 解决 react 项目 css 样式互相影响的问题

  2. 自定义命名规则

  上面生称的类名,完全是自动生成,如果自己自己规定命名规则呢,也是很简单的,只需要在上面配置modules后面添加&localIdentName=配置规则,如:

'css-loader?modules&localIdentName=[name]__[local]-[hash:base64:5]' //style__bgRed-2R9YN,local对应所在文件夹名,local对应文件名,最后是哈希值

CSS Modules 解决 react 项目 css 样式互相影响的问题

  3. 全局类名和本地类名

  我们可以使用:global(className)来标识这个类是全局类名,因此CSS Modules不对其类名进行转化,:local(className)则相反,如果不用这两个包裹的话,默认是local.

style.scss

/\* style.scss \*/
.bgRed {
    background-color: #f00;
}

// 添加全局bgRed
:global(.bgRed) {

}

app/app.js

/\* app/app.js \*/

import React, {Component} from 'react';
import ReactDOM from 'react-dom';
/\* 引入我们定义的.scss文件 \*/
import styles from '../style/style.scss';

/\* 使用无状态函数定义我们的组件\*/
function Title() {
    console.log(styles);
    return (
        /\* 在组件中全局的bgRed,此时我们可以访问到我们全局定义的bgRed,它并没有被转化 \*/
        <h1 className="bgRed"}>Hello React!</h1>
    );
}

/\* 渲染到页面中 \*/
ReactDOM.render(<Title />, document.body );

  4. 使用composes组合样式

  我们知道,node.js中,我们可以用require引入模块,然后使用它们。CSS Modules也提供了composes来该文件中的样式规则,甚至引用其它文件中的样式规则。

style/style.scss

/\* style/style.scss \*/

.fontWhite {
    color: #fff;
}
.bgRed {
    composes: fontWhite;
    background-color: #f00;
}

app/app.js

/\* app/app.js \*/

import React, {Component} from 'react';
import ReactDOM from 'react-dom';
/\* 引入我们定义的.scss文件 \*/
import styles from '../style/style.scss';

/\* 使用无状态函数定义我们的组件\*/
function Title() {
    console.log(styles);
    /\* 打印引入的styles,是一个包含连个属性的对象,其值就是自动生成的类名
        Object {fontWhite: "style\_\_fontWhite-3jipu", bgRed: "style\_\_bgRed-2R9YN style\_\_fontWhite-3jipu"}rx\_o02FHxKTBzC"}
     \*/
    return (
        /\* 在组件中引用 \*/
        <h1 className={styles.bgRed}>Hello React!</h1>
    );
}

/\* 渲染到页面中 \*/
ReactDOM.render(<Title />, document.body )

此时,就是添加了两个类,html结构如下图:

CSS Modules 解决 react 项目 css 样式互相影响的问题

引入其它文件中的样式规则,写composes: className(要引入的类名) from '引入的文件路径即可',最终效果同上,composes多少规则,就添加多少类。

最后:大家有名有发现,我一直都在类上做文章,那是因为CSS Modules只转换class名相关的样式。大家要注意啦。

在最后,给大家提供一个js库——classnames类库,给我的感觉和angular中的ng-class差不多,将值为true的类添加上。

9
94SAMA
暂时因缘,百年之后,各随六道,不相系属。
1
发布数
0
关注者
260
累计阅读

热门教程文档

MyBatis
19小节
Spring Boot
24小节
MySQL
34小节
Flutter
105小节
Next
43小节