css-module 嵌套組件樣式修改

由于原生CSS的規(guī)則都是全局的,任何一個(gè)組件內(nèi)的樣式規(guī)則,都會(huì)對(duì)全部組件生效,導(dǎo)致全局樣式污染;
為了解決這個(gè)問題,我們可以給不同的頁面寫不同的類名,但是這樣特別的繁瑣,而且多人協(xié)同開發(fā)難免會(huì)出現(xiàn)類名重復(fù);
css-module 解決了這個(gè)問題,通過自動(dòng)附上獨(dú)一無二的哈希字符串(需配置),避免選擇器重名;
在使用css-module 時(shí)會(huì)發(fā)現(xiàn)當(dāng)前組件樣式表的類樣式對(duì)嵌套組件內(nèi)的類不生效的情況,以下是嵌套自定義組件和antd組件的例子
注:以下樣式因項(xiàng)目設(shè)置可能與原本的antd組件風(fēng)格有些不同,但不影響原理理解


  • 示例
// DemoPage 組件
import { List } from 'antd';
const { Item } = List;
import styles from './DemoPage.less';
import MyComponent from './MyComponent'

render() {
  const demoList = [
    {
      id: 1,
      text: '這里是antd的 list 組件內(nèi)部1111'
    },
    {
      id: 2,
      text: '這里是antd的 list 組件內(nèi)部2222'
    },
  ]
  return (
    <div className={styles.root}>
      <div>no class (這里是原生元素div)</div> 
      <div className='ant-list-item'>no style (這里是原生元素div)</div>
      <div className={styles['ant-list-item']}>has styles (這里是原生元素div)</div>
      <List bordered style={{marginTop: '30px', border: '1px solid rgb(34, 177, 76)'}}>
        {demoList.map(item => (
          <Item key={item.id}>
            {item.text}
          </Item>
        ))}
      </List>
      <MyComponent></MyComponent>
    </div>
  );
}
// MyComponent 組件
import React from "react";

import styles from "./MyComponent.less";

const MyComponent = function MyComponent(props) {
  return (
    <div style={{marginTop: '30px', border: '1px solid rgb(255, 128, 64)'}}>
      這里是自定義組件
      <div>no class (這里是原生元素div)</div> 
      <div className='ant-list-item'>no style (這里是原生元素div)</div>
      <div className={styles['ant-list-item']}>has styles (這里是原生元素div)</div>
    </div>
  );
}

export default MyComponent;
  • 初始樣式效果(以下皆指DemoPage組件的樣式表)
.root {
  background-color: #fff;
  padding: 24px 32px;
  border-radius: 4px;
}
初始樣式效果.png
  • 問題:樣式表里寫的類名無法對(duì)內(nèi)部嵌套組件的同類名元素生效,因?yàn)橥ㄟ^編譯后的樣式表都會(huì)帶上唯一的哈希后綴,而自定義組件和antd等外部引入的組件類名沒有該后綴,所以無法匹配
// 編譯后類名類似 root___xxxx
// xxxx指生成的哈希字符串
.root {
  background-color: #fff;
  padding: 24px 32px;
  border-radius: 4px;

  // 編譯后類名類似 ant-list-item___oooo
  // oooo指生成的哈希字符串,不同類名生成的哈希字符串不同
  .ant-list-item {
    background-color: red;
  }
}
只對(duì)引入該樣式表的當(dāng)前組件生效.png

不同的哈希字符串導(dǎo)致了嵌套組件的樣式不生效.png
  • 解決嵌套組件樣式不生效問題:在類名外嵌套:global,凡是這樣聲明的class,在樣式表被編譯時(shí)都不會(huì)被編譯成哈希字符串,即類名會(huì)保持原樣,即可作用于引用的antd組件或未使用樣式表的自定義組件類名
// 編譯后 root___xxxx
.root {
  background-color: #fff;
  padding: 24px 32px;
  border-radius: 4px;

  // 編譯后 ant-list-item; global下的(包括嵌套)類名都不會(huì)帶上哈希字符串
  // 相當(dāng)于
  // .root___xxxx .ant-list-item {
  //   background-color: red;
  // }
  :global {
    .ant-list-item {
      background-color: red;
    }
  }
}
添加 :global 后.png
  • 樣式表里用 元素選擇器,會(huì)對(duì)該樣式表下的所有(包括組件內(nèi))的元素生效
// 編譯后 root___xxxx
.root {
  background-color: #fff;
  padding: 24px 32px;
  border-radius: 4px;

  // 元素選擇器編譯后還是元素,不帶哈希值所以還是能影響組件內(nèi)部組件的樣式
  div {
    background-color: red;
  }
}
css-module中的元素選擇器會(huì)照常生效.png
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容