我经历的css阶段
原生css阶段
一年前我初次接触了react,在此之前我一直使用的vue框架。相对于vue将组件的style作为模板的一部分,react没有任何的限制。当时只能使用原始的方式:每个组件一个css文件,将其引入组件,每个css选择器前加上一堆前缀防止样式覆盖。
这么做是能实现功能,但对于组件化来说它组件和样式没有耦合,还是有可能出现样式覆盖问题的。而且前面一堆前缀也不太优雅难以管理维护。
css Module阶段
第二个阶段就是css模块化,在独立完成了第一个react项目后,我复盘了其中遇到的问题,并且寻求解决方案。后来有幸读到了阮一峰大大的一篇介绍css module的文章:
链接: CSS Modules 用法教程
下面是我在项目中的用法举例:
css文件:
:global(.menu-wapper){
color:green;
}
:local(.sub-menu){
color:red;
}
:global(#root) :local(.name){}
js文件:
import styles from "./index.css";
import React from 'react';
import ReactDOM from 'react-dom';
import classNames from "classnames";
const ComposeMenu = function(props){
return <div>
<div className={'menu-wapper'}>111</div>
<div className={classNames(styles['sub-menu'],`submenu-${props.index}`)}>222</div>
</div>
}
ReactDOM.render(
<ComposeMenu index="1"/>,
document.getElementById('root')
);
编译后生成:
css:
.menu-wapper{
color:green;
}
.index_sub-menu_yWNJ9{
color:red;
}
#root .index_name__Ol1S{}
引入的styles是个类模块的东西,可以通过.访问css规则。配合一些classNames之类的库使用十分方便。css文件中的选择器会根据路径文件名等加上哈希字符作为class名,实现了类似于作用域的效果,当然如果不想被编译需要加上:global()保持原来的class名,两者也可以混用。在阮一峰大大的日志里都挺详细的,就不多介绍了,配合less和sass使用也没问题。
JSS解决方案
jss顾名思义,就是通过js生成css。他可以直接使得css的表达能力提升到js水准,变量、复杂计算等都没啥问题。在react中可实现将组件和样式放在同一个文件中,真正实现样式组件的耦合。linaria就是个优秀的jss库,这个来源于我看到的一篇掘金文章:Linaria 也许是现在 React 最佳的 JSS 方案.
这个好在它是零运行时,即使禁用js也不会影响css加载。它在打包时就已经生成相应的css文件和class名。
那就看看如何使用吧:
import {css} from 'linaria';
import { styled } from 'linaria/react';
import React from 'react';
import ReactDOM from 'react-dom';
const name = css`color:green;`;//基于模板函数
const Wrap = styled.div`color:red
&::after{
content:"";
width:10px;
height:10px;
display:block;
background:#999;
}
`;
const ComposeMenu = function(props){
return <div>
<div className={name}>111</div>
<Wrap>222</Wrap>
</div>
}
ReactDOM.render(
<ComposeMenu index="1"/>,
document.getElementById('root')
);
可以通过linaria直接生成class名或者组件,下面是它生成的css:
.n166f1hf{color:green;}
.w18oyai6{color:red;}
.w18oyai6::after{content:"";width:10px;height:10px;display:block;background:#999;}
效果如图:
webpack的配置按照github的文档即可,你可能会遇到报错:Add @babel/preset-react (https://git.io/JfeDR) to the ‘presets’ section of your Babel config to enable transformation .这种提示你添加babel插件而你实际上已经设置相应的plugins的问题,应该是linaria/loader处理时和jsx语法冲突问题,需要额外添加.babelrc文件设置全局的presets.