一、认识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 = 18function 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};
`