CSS模块postcss-modules,在jsx中实现vue里的scoped

简介: CSS模块postcss-modules,在jsx中实现vue里的scoped

深入探索CSS Modules与PostCSS:在JSX中实现Vue风格的Scoped样式

随着前端技术的不断发展,组件化开发已经成为现代前端开发的标配。在组件化开发中,如何确保组件的样式不会影响到其他组件,是一个需要解决的问题。ue通过scoped属性提供了一种优雅的解决方案,而在React和其他基于JSX的框架中,我们可以通过结合使用CSS Modules和PostCSS来达到类似的效果。

本文将详细介绍如何在基于JSX的项目中(如React、Preact等)利用CSS Modules和PostCSS来模拟Vue的scoped样式功能,确保样式的局部性和组件的独立性。

什么是CSS Modules?

CSS Modules是一种将CSS类名局部化的技术,它允许你在一个组件的样式中使用简单的类名,而不必担心与其他组件的类名冲突。通过使用CSS Modules,每个组件的CSS类名都会被转换成一个独一无二的字符串,从而保证了样式的隔离性。

CSS Modules的核心概念

  • 局部作用域:CSS Modules通过为每个类名添加一个独一无二的哈希后缀来创建局部作用域,确保类名的唯一性。
  • 类名映射:CSS Modules会生成一个映射对象,将原始的类名映射到转换后的类名,这样你就可以在JSX中通过这个映射对象来引用样式。

如何使用CSS Modules?

使用CSS Modules通常需要你配置构建工具(如Webpack、Parcel等)来支持它。以下是一个基本的配置示例(以Webpack为例):

// webpack.config.js
module.exports = {
  // ...其他配置
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          'style-loader',
          {
            loader: 'css-loader',
            options: {
              modules: true, // 开启CSS Modules
              localIdentName: '[path][name]__[local]--[hash:base64:5]', // 自定义生成的类名格式
            },
          },
        ],
      },
    ],
  },
};

在这个配置中,我们告诉Webpack在遇到.css文件时使用css-loader,并通过options开启CSS Modules功能。

什么是Post?优化。

PostCSS是一个用于转换CSS的工具,它允许你使用插件来处理CSS代码。PostCSS本身不会做很多事情,它更像是一个平台,让你可以运行各种插件来对CSS进行转换和优化。

PostCSS与CSS Modules的结合

虽然CSS Modules已经提供了类名局部化的功能,但在某些情况下,你可能还需要对CSS代码进行其他转换,比如添加浏览器前缀、压缩代码等。这时,你可以将PostCSS与CSS Modules结合使用,通过PostCSS的插件来实现这些功能。


要在项目中同时使用CSS Modules和PostCSS,你需要在构建配置中添加相应的loader和插件。以下是一个基本的配置示例:

// webpack.config.js
module.exports = {
  // ...其他配置
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          'style-loader',
          {
            loader: 'css-loader',
            options: {
              modules: true,
              localIdentName: '[path][name]__[local]--[hash:base64:5]',
            },
          },
          {
            loader: 'postcss-loader',
            options: {
              postcssOptions: {
                plugins: [
                  [
                    'postcss-preset-env',
                    {
                      // 配置postcss-preset-env的选项
                      autoprefixer: {
                        flexbox: 'no-2009',
                      },
                      stage: 3,
                    },
                  ],
                ],
              },
            },
          },
        ],
      },
    ],
  },
};

在这个配置中,我们添加了一个postcss-loader,并通过postcssOptions配置了要使用的PostCSS插件。在这个例子中,我们使用了postcss-preset-env插件,它可以根据你的目标浏览器自动添加所需的浏览器前缀,并进行其他必要的转换。

在JSX中使用CSS Modules和PostCSS

一旦你配置好了构建工具,就可以在JSX文件中使用CSS Modules和PostCSS了。以下是一个简单的React组件示例:

import React from 'react';
import styles from './MyComponent.css'; // 导入CSS Modules样式

const MyComponent = () => {
  return (
    <div className={styles.container}>
      <h1 className={styles.title}>Hello, World!</h1>
    </div>
  );
};

export default MyComponent;

在这个例子中,我们通过import语句导入了MyComponent.css文件,这个文件包含了组件的样式。由于我们开启了CSS Modules功能,所以styles对象中的每个属性都会被转换成一个独一无二的类名。然后,我们可以在

JSX中通过styles.containerstyles.title来引用这些类名。

通过这种方式,我们可以确保MyComponent组件的样式不会影响到其他组件,从而实现了类似于Vue中scoped属性的效果。

总的来说,我们的组件需要一个全局唯一的样式名,避免污染全局样式

方式一

我们自己把组件中的样式命名的全局唯一。

方式二

使用postcss-modules

postcss-modules是一个PostCSS插件,实现了css的模块化的概念,可以单独引用,每一个引用都是一个副本或着说是一个实例,自己带着唯一标识。

例如,你有以下CSS:

/* styles.css */
:global .page {
  padding: 20px;
}

.title {
  composes: title from "./mixins.css";
  color: green;
}

.article {
  font-size: 16px;
}

/* mixins.css */
.title {
  color: black;
  font-size: 40px;
}

.title:hover {
  color: red;
}

经过改造后会变成这样:

._title_116zl_1 {
  color: black;
  font-size: 40px;
}

._title_116zl_1:hover {
  color: red;
}

.page {
  padding: 20px;
}

._title_xkpkl_5 {
  color: green;
}

._article_xkpkl_10 {
  font-size: 16px;
}

插件会为转换后的类提供一个JSON对象:

{
  "title": "_title_xkpkl_5 _title_116zl_1",
  "article": "_article_xkpkl_10"
}

在vite中使用

CSS Modules

任何以 .module.css 为后缀名的 CSS 文件都被认为是一个 CSS modules 文件。导入这样的文件会返回一个相应的模块对象:

/* example.module.css */
.red {
  color: red;
}
import classes from './example.module.css'
document.getElementById('foo').className = classes.red

CSS modules 行为可以通过 css.modules 选项 进行配置。

interface CSSModulesOptions {
  scopeBehaviour?: 'global' | 'local'
  globalModulePaths?: RegExp[]
  generateScopedName?:
    | string
    | ((name: string, filename: string, css: string) => string)
  hashPrefix?: string
  /**
   * 默认:null
   */
  localsConvention?:
    | 'camelCase'
    | 'camelCaseOnly'
    | 'dashes'
    | 'dashesOnly'
    | null
}

如果 css.modules.localsConvention 设置开启了 camelCase 格式变量名转换(例如 localsConvention: 'camelCaseOnly'),你还可以使用按名导入。

// .apply-color -> applyColor
import { applyColor } from './example.module.css'
document.getElementById('foo').className = applyColor

具体vite配置可以做个参考:

// https://vitejs.dev/config/
export default defineConfig({
    css: {
        modules: {
          // 配置localsConvention则可以开启css模块功能
            localsConvention: "camelCase", 
            hashPrefix: "data-v",
        }
    },
})

方式三

构建工具会将类名编译成一个哈希字符串,防止整个项目的类名重复。

  1. styled-components
  2. emotion

相关文章
|
4月前
|
JavaScript 前端开发
【快捷键配置】常用HTML类名、CSS样式名称、JS方法变量名、vue代码片段
【快捷键配置】常用HTML类名、CSS样式名称、JS方法变量名、vue代码片段
|
4月前
|
前端开发 JavaScript
vue 动态改变css样式
vue 动态改变css样式
110 0
|
4月前
|
前端开发
vue+ts或者react+ts如何使用animate.css
vue+ts或者react+ts如何使用animate.css
76 0
|
1月前
|
前端开发 JavaScript
使用Vue+CSS实现汉堡图标过渡为叉号图标,有点意思
本文分享了如何使用Vue和CSS实现一个汉堡图标在点击时过渡为叉号图标的动画效果,并提供了详细的实现代码和效果演示。
53 0
使用Vue+CSS实现汉堡图标过渡为叉号图标,有点意思
|
2月前
|
JavaScript 前端开发 容器
vue组件封装——固定宽高比的容器(2种方法:纯CSS实现 + JS实现)
vue组件封装——固定宽高比的容器(2种方法:纯CSS实现 + JS实现)
90 2
|
2月前
|
JavaScript 前端开发
vue 模拟随机变速的动态打字特效【支持多行文本】(含css实现闪烁光标,js动态改变setInterval定时器的时间间隔)
vue 模拟随机变速的动态打字特效【支持多行文本】(含css实现闪烁光标,js动态改变setInterval定时器的时间间隔)
52 1
|
2月前
|
前端开发 JavaScript
vue实战范例——箭头步骤条/导航(含css 斜切skew的妙用)
vue实战范例——箭头步骤条/导航(含css 斜切skew的妙用)
139 0
|
2月前
|
前端开发 JavaScript
vue 自定义气泡弹窗 $pop (内含css晃动动画shake制作)
vue 自定义气泡弹窗 $pop (内含css晃动动画shake制作)
37 0
|
2月前
|
JavaScript 内存技术
Vue动画——使用最新版Animate.css教程
Vue动画——使用最新版Animate.css教程
176 0
|
3月前
|
前端开发 JavaScript