前言
在多人开发的时候,或者说二开的时候,不知道大家有没有这样一种体会:
- 我明明给一个组件添加
className 了,居然样式不生效?!仔细一看,我靠,原来是别人写的样式影响了我的这个组件的样式,或者说他正好className 和我一样,改他的样式吧,又怕影响他,改我的样式吧,又烦,而且别人下次写样式,也有可能会受我的这个影响。 - 每次我创一个组件,就要另外新建一个
.css 文件,而且样式又不是很多,但偏偏要新建一个文件,就很烦,而且还要自己想一个className ,我懒!直接写在组件上吧,多起来了又显得代码不整洁。 - 如果组件的样式是动态的,需要根据别人传的
props 来决定,那我又要面临事先写好两套样式,想两个className - 既然
react 里面支持jsx 语法,那我就相当于可以把html代码 写在js文件 ,那为什么就不能在js文件 里面写css代码 ?如果支持的话,不说一定很爽,但至少也可以带来不一样的体验
Tip: 这个时候可能会有人会想到用sass + css module 的方案来解决上面的一些问题和疑问,但你都来看这篇文章了,想必你想寻找更好的解决办法,或者说css module 也没想到,那这个可以看下阮一峰大佬的文章
正片
在项目中,往往会这样给一个组件加样式:
import "./App.css"
function App() {
return (
<div className="app">
<p>
hello world
</p>
</div>
);
}
.app p{
background-color: burlywood;
font-size: 24px;
}
效果: 但是现在这里要介绍一种css in js 库-----styled-components ,先下载:
npm i styled-components -D
常规用法
然后我们就能将上面的常规步骤写成如下这样:
import styled from "styled-components";
const Div = styled.div`
padding: 6px;
p{
background-color: burlywood;
font-size: 24px;
}
`
function App() {
return (
<Div>
<p>
hello world
</p>
</Div>
);
}
效果: 这时你就会发现两个写法不一样,但是却能达到同样的效果,而且这个新的写法你会发现,其实就是给这个元素加上一个唯一的className ,但是不是你自己加啊,它不仅可以可以应用于外层的div 元素的padding样式 ,它还能同时在里面写上后代元素p 标签,且样式也是能生效的,甚至你还可以嵌入其他className 、伪元素 、sass 写法等等,就像下面这样写:
import styled from "styled-components";
const Div = styled.div`
padding: 6px;
p{
background-color: burlywood;
font-size: 24px;
}
.test{xxx: xxx}
&:hover{
background-color: antiquewhite;
}
`
function App() {
return (
<Div>
<p>
hello world
</p>
</Div>
);
}
通过props来决定样式
import styled from "styled-components";
const Div = styled.div`
width: 100px;
padding: 5px;
margin: 10px;
text-align: center;
border: 2px solid pink;
background-color: ${(props) => {
console.log(props);
return props.type === 'primary' ? '#3498db' : 'white'
}};
`
function App() {
return (
<>
<Div >
default
</Div>
<Div type='primary'>
primary
</Div>
</>
);
}
效果: 这个时候你就会发现我是通过div 的type 属性来决定它的背景色,且确实能够在你写css中使用js语法,通过${} 的形式传入一个回调函数,回调函数中props 对象里面,包括你自己加的type 属性,以及自己自带的theme 属性,如下: 而其中的children 属性其实是react它自己会给组件加一个children 属性,来代表子元素;theme 属性是用来给你传入不同的主题对象,也许为了type 不同,你可以直接应用于不同的主题,这里就不过多解释了。
控制组件的其他属性
有些元素本身是具备一些特有的属性的,如input 的type 属性,button 的onclick 属性,你可以这样写:
import styled from "styled-components";
const Input = styled.input.attrs({
type: 'text'
})``
const Password = styled.input.attrs({
type: 'password'
})``
const Button = styled.button.attrs({
onClick: () => {
console.log('按钮被点击了...');
}
})``
function App() {
return (
<>
<Input />
<br />
<Password />
<br />
<Button>按钮</Button>
</>
);
}
也确确实实可以控制元素本身的一些属性
css混入(mixin、变量化)
import styled, { css } from "styled-components";
const complexMixin = css`
color: ${props => (props.redColor ? 'red' : 'black')};
`
const StyledComp = styled.div`
${props => (props.complex ? complexMixin : 'color: blue;')};
`
function App() {
return (
<>
<StyledComp>
无complex
</StyledComp>
<StyledComp complex redColor>
有complex 且 redColor
</StyledComp>
</>
);
}
效果:
keyframes变量化
import { keyframes } from 'styled-components';
const fadeIn = keyframes`
0% {
opacity: 0;
}
100% {
opacity: 1;
}
`;
const FadeInButton = styled.button`
animation: 1s ${fadeIn} ease-out;
`;
总结
当然我上面讲诉的是一些比较常用的用法,更多的你可以看下官网文档,不过看了那么多例子,想必也会有些体会: 优点:
- 它能让你组件拥有一个唯一的
className ,不同文件的之间的组件不会受到彼此之间的影响 - 它能让你的
css 支持js 语法,从而更加的灵活,而且还能让你同时享受sass 写法 - 如果你现在就想使用,直接下载依赖包就可以了,不用担心之前的写法不兼容,友好升级
那有没有缺点呢? 我自己体会到的,不知道算不算是缺点:
- 虽然可以不用再专门创建一个
css 文件了,但是如果组件多了,那我这个js 文件岂不是越来越大?,越写越多?那后面维护,岂不是很难受? - 我已经习惯于把
js 和css 分开写的习惯了,且react中jsx 里面本来也可以直接在组件上面写样式 - 如果这个项目是自己一个人写,用这种可能是挺方便的,人多了,是不是还不如用
css module ? - 本质上它是在
js 运行时,通过webpack 的一些loader 向header 标签里面插入style 标签,这无疑会增加js文件的加载效率 - 如果不能把css抽离出去,那岂不是不能享受缓存?
总之看个人和项目吧,这篇文章也仅是学习和记录
|