内联样式
内联样式是官方推荐的一种 CSS 样式写法:
Style 接受一个采用小驼峰命名属性的 JS 对象,而不是CSS字符串;
可以引用 state 中的状态来设置相关的样式。
render() {
const pStyle = {
color: 'orange'
}
return (
<div style={{ fontSize: '50px', color: 'red' }}>
Hello World
</div>
<p style={pStyle}>
Hello React
</p>
)
}
优点
样式之间不会有冲突;
可以动态的获取当前 state 中的状态。
缺点
写法上都需要驼峰标识;
某些样式没有提示;
大量的样式,使代码混乱;
某些样式无法编写(如伪元素)。
普通CSS
普通 CSS 我们通常会编写到一个单独的文件,之后再进行引入;
这样的编写方式和普通的网页开发中编写方式是一致的;
但我们希望组件是一个独立的模块,即使是样式也只在组件内部生效,不会互相影响;
但普通的 CSS 都属于全局效果,样式之间会互相影响;
普通 CSS 会出现样式之间互相层叠掉。
CSS modules
CSS modules 并不是 React 特有的解决方案,而是所有使用了类似于 webpack 配置的环境下都可以使用的。
React 脚手架已经内置了 CSS modules 的配置。
CSS 代码:
.title {
color: red;
}
在需要引入 CSS 的文件中进行如下处理:
import React from 'react'
import appStyle from './style.module.css'
...
return (
<h2 className={appStyle.title}>Hello World</h2>
)
优点:
- 解决了局部作用域的问题,CSS 代码间不会相互影响。
缺点:
引用的类名不能使用连接符(.title-header),在JS中无法识别;
所有 className 都必须使用 {style.className} 的形式来编写;
不方便动态来修改某些样式,依然需要使用内联样式的方式。
CSS in JS
CSS in JS 是一种模式,其中 CSS 由 JS 生成而不是在外部文件中定义。
此功能并不是 React 的一部分,而是由第三方库提供。React 对样式如何定义并没有明确的态度。
在传统的前端开发中,我们通常会将结构(HTML)、样式(CSS)、逻辑(JavaScript)进行分离。
但在 React 中,认为逻辑本身和 UI 是无法分离的,所以才有了 JSX;
样式也是 UI 的一部分;
React 重要的观点之一便是“All in JS”。
styled-components
目前(2023)styled-components 是社区最流行的 CSS in JS 库。
- 安装 styled-components:
yarn add styled-components
安装 vscode-styled-components 插件;
引入库并使用:
import React, { PureComponent } from 'react'
import styled from 'styled-components'
const AppWrapper = styled.div`
font-size: 50px;
color: red;
.banner { // CSS嵌套语法
background-color: pink;
span {
color: white;
&.active { // 对<span className="active"></span>产生影响
color: red;
}
&:hover { // 意味span:hover {}
color: aquamarine;
}
&::after {
content: '!';
}
}
}
`
export default class App extends PureComponent {
render() {
return (
<AppWrapper>
Hello World
<div className='banner'>
<span>Hello React </span>
<span className='active'>Hello React </span>
<span>Hello React </span>
</div>
</AppWrapper>
)
}
}
- 分文件时的引入和导出问题:
// 需引入CSS的组件:
import {AppWrapper} from './style' // 解构赋值
// CSS文件:
import styled from 'styled-components'
export const AppWrapper = styled.div`
......
`
属性穿透和attrs的使用
如果遇上 HTML 标签自带的属性,那么 styled-components 有两种解决方案:
- 方案一:
// CSS文件:
export const Input = styled.input`
background-color: pink;
`
// 需求组件:
<Input type='password'/> // 发生了属性穿透,正常显示
- 方案二:
// CSS文件:
export const AttrsInput = styled.input.attrs({
placeholder: 'Sytus',
type: 'text' // 参数是一个对象,会重新返回一个函数
})`
color: red;
`
// 需求组件:
<AttrsInput/>
其中方案二的能力更为强大:
const HYInput = styled.input.attrs({
bcolor: 'red'
})`
border-color: ${props => props.bcolor};
color: ${props => props.color};
` // porps 会收集 attrs 和 组件传进来的参数
export default class App extends PureComponent {
constructor(props) {
super(props)
this.state = {
color: 'pink'
}
}
render() {
return (
<div>
<HYInput type="password" color={this.state.color} />
</div>
)
}
}
属性继承
const HYButton = styled.button`
padding: 10px 20px;
color: red;
`
// 实例代码
/*const HYPrimaryButton = styled.button`
padding: 10px 20px;
color: white;
`*/
const HYPrimaryButton = styled(HYButton)`
color: white;
`
export default class App extends PureComponent {
render() {
return (
<div>
<HYButton>这是普通按钮</HYButton>
<HYPrimaryButton>这是主要按钮</HYPrimaryButton>
</div>
)
}
}
主题
父组件中引入主题:
import styled, {ThemeProvider} from 'styled-components'
父组件中 return 函数内:
return (
<ThemeProvider theme={{themeColor: 'pink', fontSize: '30px'}}>
<Home />
</ThemeProvider>
)
Home 组件的 CSS 文件 中:
export const HomeStyle = styled.H2`
color: ${props => props.themeColor};
font-size: ${props => props.fontSize};
`