一、认识CSS in JS
实际上,官方文档也有提到过CSS in JS这种方案:
https://zh-hans.reactjs.org/docs/faq-styling.html
- “CSS-in-JS” 是指一种模式,其中 CSS 由 JavaScript 生成而不是在外部文件中定义;
-
注意此功能并不是 React 的一部分,而是由第三方库提供。 React 对样式如何定义并没有明确态度;
在传统的前端开发中,我们通常会将结构(HTML)、样式(CSS)、逻辑(JavaScript)进行分离。
- 但是在前面的学习中,我们就提到过,React的思想中认为逻辑本身和UI是无法分离的,所以才会有了JSX的语法。
- 样式呢?样式也是属于UI的一部分;
- 事实上CSS-in-JS的模式就是一种将样式(CSS)也写入到JavaScript中的方式,并且可以方便的使用JavaScript的状态;
所以React有被人称之为 All in JS;
当然,这种开发的方式也受到了很多的批评:
- Stop using CSS in JavaScript for web development
-
https://hackernoon.com/stop-using-css-in-javascript-for-web-development-fa32fb873dcc
二、认识styled-components
批评声音虽然有,但是在我们看来很多优秀的CSS-in-JS的库依然非常强大、方便:
- CSS-in-JS通过JavaScript来为CSS赋予一些能力,包括类似于CSS预处理器一样的样式嵌套、函数定义、逻辑复用、动态修改状态等等;
- 依然CSS预处理器也具备某些能力,但是获取动态状态依然是一个不好处理的点;
- 所以,目前可以说CSS-in-JS是React编写CSS最为受欢迎的一种解决方案;
目前比较流行的CSS-in-JS的库有哪些呢?
1. styled-components
2. emotion
3. glamorous
目前可以说styled-components依然是社区最流行的CSS-in-JS库,
所以我们以styled-components的讲解为主:
安装styled-components:
yarn add styled-components
三、ES6标签模板字符串
ES6中增加了模板字符串的语法,这个对于很多人来说都会使用。 但是模板字符串还有另外一种用法:标签模板字符串(Tagged Template Literals)。
我们一起来看一个普通的JavaScript的函数:
正常情况下,我们都是通过 函数名() 方式来进行调用的,
其实函数还有另外一种调用方式:
如果我们在调用的时候插入其他的变量:
- 模板字符串被拆分了;
- 第一个元素是数组,是被模块字符串拆分的字符串组合;
-
后面的元素是一个个模块字符串传入的内容;
在styled component中,就是通过这种方式来解析模块字符串,最终生成我们想要的样式的
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<script>
const name = 'zep'
const age = 18
function test (...args) {
console.log(args)
}
test(`my name is ${name}, age is ${age}`)
test`my name is ${name}, age is ${age}`
</script>
</body>
</html>
四、styled的基本使用
styled-components的本质是通过函数的调用,最终创建出一个组件:
- 这个组件会被自动添加上一个不重复的class;
-
styled-components会给该class添加相关的样式;
另外,它支持类似于CSS预处理器一样的样式嵌套:
- 支持直接子代选择器或后代选择器,并且 直接编写样式;
- 可以通过&符号获取当前元素;
-
直接伪类选择器、伪元素等;
import React, {PureComponent} from 'react';
import styled from 'styled-components'
const HomeWrapper = styled.div`
font-size: 30px;
color: skyblue;
.banner {
background-color: darkolivegreen;
span {
display: flex;
flex-wrap: wrap;
color: #fff;
&.active {
color: #f90;
}
&:hover {
color: pink;
}
&::after {
content: 'aaa';
}
}
}
`
const TitleWrapper = styled.h2`
text-decoration: underline;
font-size: 18px;
`
class App extends PureComponent {
render() {
return (
<HomeWrapper>
<TitleWrapper>我是home的标题</TitleWrapper>
<div className='banner'>
<span>轮播图1</span>
<span className='active'>轮播图2</span>
<span>轮播图3</span>
<span>轮播图4</span>
</div>
</HomeWrapper>
);
}
}
export default App;
在实际项目中的写法:
五、styled-components 中的props、attrs属性
- props可以穿透
2. props可以被传递给styled组件
- 获取props需要通过${}传入一个插值函数,props会作为该函数的参数;
- 这种方式可以有效的解决动态样式的问题;
-
添加attrs属性
import React, {PureComponent} from 'react';
import styled from 'styled-components'
const HYInput = styled.input.attrs({
placeholder: 'zep',
bColor: 'red'
})`
background-color: lightblue;
border-color: ${props => props.bColor};
color: ${props => props.color}
`
class App extends PureComponent {
constructor(props) {
super(props);
this.state = {
color: 'blue'
}
}
render() {
return (
<div className="profile">
<input type="password"/>
<HYInput type="text" color={this.state.color}/>
<h2>我是profile的标题</h2>
<ul className="settings">
<li>设置列表1</li>
<li>设置列表2</li>
<li>设置列表3</li>
</ul>
</div>
);
}
}
export default App;
六、styled高级特性
-
支持样式的继承
-
styled设置主题
import React, {PureComponent} from 'react';
import Home from '../home'
import Profile from '../profile'
import styled, {ThemeProvider} from "styled-components";
const HYButton = styled.button`
padding: 10px 20px;
color: red;
border-color: red;
`
// 继承样式
const HYPrimaryButton = styled(HYButton)`
//padding: 10px 20px;
//border-color: red;
color: #fff;
background-color: green;
`
/*const HYPrimaryButton = styled.button`
padding: 10px 20px;
border-color: red;
color: #fff;
background-color: green;
`*/
class App extends PureComponent {
render() {
return (
<ThemeProvider id="app" theme={{themeColor: 'yellow', fontSize: '30px'}}>
<div>app</div>
<hr />
<Home />
<hr />
<Profile />
<HYButton>我是普通的按钮</HYButton>
<HYPrimaryButton>我是primary的按钮</HYPrimaryButton>
</ThemeProvider>
);
}
}
export default App;
import styled from "styled-components";
export const HomeWrapper = styled.div`
font-size: 30px;
color: skyblue;
.banner {
background-color: darkolivegreen;
span {
display: flex;
flex-wrap: wrap;
color: #fff;
&.active {
color: #f90;
}
&:hover {
color: pink;
}
&::after {
content: 'aaa';
}
}
}
`
export const TitleWrapper = styled.h2`
text-decoration: underline;
font-size: 18px;
color: ${props => props.theme.themeColor};
`