解决样式冲突问题(css-in-js与module)

599 阅读2分钟

起源

样式冲突问题在日常开发中十分常见,在vue和react开发中,样式经过打包,被放到了同一个css文件下,最后样式就会被全局使用。这时候,如果存在重名样式名,就很可能会产生冲突。

解决方案

今天要讲解的方案是目前较为主流的两种方案:1.css-in-js 2.module 他们都是通过给类名一段哈希值来使样式名不可能重复,从而解决冲突。

一、css-in-js

css-in-js 是一种将css也用js来使用的一种思想,他比较契合react all-in-js的思想。但是这种思想现在也仍存在争议。

目前主流的css-in-js库为 styled-components。styled-components通过创造组件应用我们所传递的样式属性。

创建style组件

import styled from "styled-components"

const Wrapper = styled.div`
    width : ${props => props.width};
    height : ${props => props.height};
    background: ${props => props.color};
    display: inline-block;
    `

export default Wrapper;

应用style组件

import Wrapper from './pages/css-in-js';
import './App.css';

function App() {
  return (
    <div className="App">
      <header className="App-header">
        <Wrapper width='100px' height='100px' color='red'></Wrapper>
      </header>
    </div>
  );
}

export default App;

最终效果

image.png

从上图可以看出来,Wrapper组件最后变成了我们一开始指定的div,同时作为组件,我们可以通过传入属性值来控制他的样式。如果你想同时应用别的style组件,或许就需要再裹上一层组件,这样会破坏html元素的结构,style-components通过继承的思想解决了这个问题。创造的style组件可以通过继承,得到别的style组件的样式。这里属性名也被带到了标签上,个人觉得这样可能会存在一些隐患,同时也不利于阅读,完全没有展示的必要,如果大家有别的看法欢迎讨论。

二、module样式

这种方法在react开发中比较常用,只需要在样式文件名和css之间加上.module就可以生成。

App.module.css

.bar {
    width: 100px;
    height: 100px;
    background: blue;
    display: inline-block;
}
.bar .test{
    color: red;
}

test.module.css

.bar {
    width: 100px;
    height: 100px;
    background: blue;
    display: inline-block;
}

应用

import './App.css';
import styled from './App.module.css';
import testStyled from './test.module.css';
function App() {
  return (
    <div className="App">
      <header className="App-header">
        <div className={styled.bar}>
          <div className={styled.test}>11</div>
        </div>
        <div className={testStyled.bar}></div>
        <div className={styled.test}>11</div>
      </header>
    </div>
  );
}
export default App;

最终效果

image.png

从上图可以看到,module生成的样式名采用文件名+类名+哈希值生成,所以不会存在重复的样式名。同时我尝试使用子类选择器,最后,子类选择器同样是有效的。module样式的使用思路实际上和传统的思路是一样的,如果是想要使用多个样式,那重复指定就可以。