0%

React中的CSS

React中的过渡动画

  • 动画插件:react-transition-group
  • npm install react-transition-group —save

Transition

与框架无关,常见的CSS动画使用方法:

1
2
3
4
5
6
7
8
.start{
position: relative;
left:10px;
}
.end{
left:20px;
transition:left 1s ease;
}

CSSTransition

CSSTransition具有三种状态

  • 开始状态,对应的类是-appear、-enter、-exit
  • 执行动画,对应的类是-appera-active、-enter-active、-exit-active
  • 执行结束,对应的类是-appera-done、-enter-done、-exit-done

CSSTransition常见属性:

  • in:触发进入或退出状态

    • 如果添加了unmountOnExit={true},那么该组件会在执行退出动画结束后被移除掉
    • 当in为true时,触发进入状态,会添加-enter、-enter-acitve的class开始执行动画,当动画执行结束后,会移除两个class, 并且添加-enter-done的class
    • 当in为false时,触发退出状态,会添加-exit、-exit-active的class开始执行动画,当动画执行结束后,会移除两个class,并 且添加-enter-done的class
  • classNames:动画class的名称

    • 决定了在编写css时,对应的class名称:比如card-enter、card-enter-active、card-enter-done
  • timeout:动画过渡的时间,指的是动画执行后添加-enter-done的时间,动画真实执行时间由transition决定

  • appear:是否在初次进入添加动画(appear和in都要为true、同时要设置-appear类)

  • CSSTransition的钩子函数:

    • onEnter:在进入动画之前触发
    • OnEntering:在进入动画时触发
    • OnEntered:在应用进入动画结束时触发
    • ……

css代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
 /*设置初始状态,不发生动画的状态,可以用appear的三个类替代*/
h2{
position: relative;
opacity: 0;
left: 0;
}
.h2show-enter{
opacity: 0;
left: 0;
}
.h2show-enter-active{
left: 100px;
opacity: 1;
transition: all 2s ease;
}
/*不设置done那么在动画执行完成那一刻会立即恢复到之前的状态,看是否需要恢复编写此类*/
.h2show-enter-done{
opacity: 1;
left: 100px;
}
.h2show-exit{
opacity: 1;
left: 100px;
}
.h2show-exit-active{
left: 0;
opacity: 0;
transition: all 2s ease;
}
/*不设置done那么在动画执行完成那一刻会立即恢复到之前的状态,看是否需要恢复编写此类*/
.h2show-exit-done{
left: 0;
opacity: 0;
}

jsx代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
import React from "react";
import { CSSTransition } from "react-transition-group";
import "./index.css"
//编写组件
class App extends React.PureComponent{
constructor(){
super()
this.state ={
isShow:false
}
}
change(){
this.setState({
isShow:!this.state.isShow
})
}
render(){
const {isShow} = this.state
console.log(isShow)
return (
<div>
<button onClick={()=>{this.change()}}>变化</button>
<CSSTransition in={isShow} classNames="h2show" timeout={2000} unmountOnExit={true}>
<h2>哈哈哈</h2>
</CSSTransition>
</div>
)
}
}
export default App

SwitchTransition

  • 控件两种状态之间的切换:on和off指定两种状态

  • mode属性:

    • in-out:新组件先进入,旧组件再移除

    • out-in:旧组件先移除,新组件再进入

  • SwitchTransition组件里面要有CSSTransition或者Transition组件,不能直接包裹要切换的组件

  • SwitchTransition里面的CSSTransition或Tasnsition组件不再像之前那样接受属性来判断元素状态,取而代之的是key属性

css代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
h2{
position: relative;
left: 100px;
}
.h2show-enter{
left: 0;
}
.h2show-enter-active{
left: 100px;
transition: all 2s ease;
}
.h2show-enter-done{
left: 100px;
}
.h2show-exit{
left: 100px;
}
.h2show-exit-active{
left: 0;
transition: all 2s ease;
}
.h2show-exit-done{
left: 0;
}
  • 起始状态可以没有,那么刚开始就是默认状态
  • out-in模式:先制性exit代码,再执行enter代码,没有h2show-enter-done,动画执行结束会回归初始状态,可以没有h2show-exit-done
  • in-out模式:先执行enter代码,再执行exit代码,没有h2show-exit-done,动画结束会回归初始状态,可以没有h2show-enter-done

jsx代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
import React from "react";
import { CSSTransition,SwitchTransition } from "react-transition-group";
import "./index.css"
//编写组件
class App extends React.PureComponent{
constructor(){
super()
this.state ={
isShow:false
}
this.nodeRef = React.createRef()
}
change(){
this.setState({
isShow:!this.state.isShow
})
}
render(){
const {isShow} = this.state
console.log(isShow)
return (
<div>
<button onClick={()=>{this.change()}}>变化</button>
<SwitchTransition mode="in-out">
<CSSTransition
nodeRef = {this.nodeRef}
key={isShow?"exit":"login"}
classNames="h2show"
timeout={2000}
>
<h2 ref={this.nodeRef}>{isShow?"哈哈哈":"哈你妹"}</h2>
</CSSTransition>
</SwitchTransition>
</div>
)
}
}
export default App

TransitionGroup:

  • 有一组动画时,可以将这些CSSTransition放入到TransitionGroup中

有些搞不懂,官网看教程吧

React中CSS的编写

CSS组件化!!!:

  • 可以编写局部css:css具备自己的局部作用域,不会污染其他组件的元素
  • 可以编写动态css:可以获取当前组件的一些状态,根据状态生成不同的css样式
  • 支持所有的css特性:伪类、动画、媒体查询等
  • 编写起来简单方便,符合一贯的css风格特点

内联样式

  • style接受小驼峰命名属性的JavaScript对象,而不是字符串
  • 可以接受state中的状态来设置相关的格式

内联样式优点:

  • 样式之间不会有冲突
  • 可以动态获取当前state中的状态

内联样式缺点:

  • 都需要驼峰标识
  • 某些样式没有提示
  • 大量样式,代码混乱
  • 某些样式无法编写,比如伪类/伪元素

普通CSS

  • 将CSS编写到一个单独的文件,之后进行引入

  • 和普通网页开发中的编写方式一致

    • 按照普通的网页标准去写,那么不会有太大的问题

    • 但是组件化开发中我们总是希望组件是一个独立的模块,样式只在自己内部生效,不会相互影响

    • 但是普通的CSS都属于全局的CSS,样式组件会相互影响
  • 这种编写方式的最大问题是样式之间会相互层叠掉

CSS modules

  • 将.css文件修改为.module.css看就可以引用并且局部使用
  • 但是类名不能使用(.home-title),因为JavaScript不识别-
  • 所有的className都必须使用{style.className}的形式来编写
  • 不方便动态的修改某些样式,依然需要使用内联样式的方式

CSS in Js

CSS in Js是一种模式,其中CSS有javaScript生成而不是在外部文件中定义

  • 传统的前端开发中,HTML、CSS、JavaScript通常分类
  • React认为逻辑和UI是无法分离的,所以才会有了JSX的语法
  • JSX是Html in Js,加上CSS in Js在完整的体现的逻辑和UI无法分离,因此React被称为All in JS

CSS in JS库:styled-components:

  • CSS-in-JS使用JavaScript为CSS赋予一些能力,可以类似于CSS预处理器一样的样式嵌套、函数定义、逻辑复用、动态修改
  • CSS预处理器也具备某些能力,但获取动态状态依然是一个不好处理的点

ES6标签模板字符串

image-20230329161529306

即函数可以通过字符串的方式来调用

  • 第一个参数是数组,是被模块字符串拆分后的组合
  • 后面的元素是一个个模块字符串传入的内容
  • 注意是反引号

styled-components的使用

基本使用

jsx代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import React from "react";
import { AppWrapper, StrongWrapper} from "./style";
//编写组件
class App extends React.PureComponent{
constructor(){
super()
}
render(){
return (
<AppWrapper>
<div className="container">
<span>哈哈哈</span>
<StrongWrapper>我是strong</StrongWrapper>
<div className="context">
<span>嘿嘿嘿</span>
</div>
<div className="context1">
<span>嗯嗯嗯</span>
</div>
</div>
</AppWrapper>
)
}
}
export default App

style.js代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import styled from "styled-components";
export const AppWrapper = styled.div`
.container>span{
width:100%;
color: red;
}
.container{
.context1{
color: orange;
}
}
.container .context{
color: blue;
}
.container .context:hover{
color: #cccc;
}
&:hover{
text-decoration: line-through;
}
`
export const StrongWrapper =styled.strong`
color:skyblue
`
  • 样式js的命名不能和组件名称相同,例如不能用App.js
  • 可以像正常CSS一样编写CSS代码
  • 可以用&来获取当前元素
  • 可以通过设置styled.__来设置包裹的类型
  • styled返回的是一个组件,可以按照组件的方法使用

props\attrs属性

  • 获取props需要通过${}传入一个插值函数,props会作为该函数的参数;
  • 这种方式可以有效的解决动态样式的问题

CSS代码:

1
2
3
4
5
6
7
8
9
10
11
12
import styled from "styled-components";
export const AppWrapper = styled.div.attrs({
tcolor:props=>(props.color||"blue")
})`
.container{
width:100%;
color: ${props=>{
return props.tcolor
}};
}

`

jsx代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import React from "react";
import { Children } from "react";
import { AppWrapper, StrongWrapper} from "./style";
//编写组件
class App extends React.PureComponent{
constructor(){
super()
this.state = {
checked:true
}
}
render(){
const {checked} = this.state
return (
<AppWrapper color={checked?"red":""}>
<div className="container">
<h2>哈哈哈</h2>
</div>
<button onClick={()=>{this.setState({checked:!this.state.checked})}}>改变颜色</button>
</AppWrapper>
)
}
}
export default App

注:

  • tcolor不能与color同名,要不然会循环拿取
  • tcolor传入的是一个函数,括号可以省略,会自动调用生成值
  • tcolor:props=>(props.color||”blue”)是为了处理不传值时给定默认值,没有默认值时可以在下面直接取

styled的继承

CSS代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
import styled from "styled-components";
export const AppWrapper = styled.div`
display: flex;
`
export const Button1 = styled.button`
border-radius: 5px;
border:1px solid red;
background-color: gray;
opacity: 0.5;
`
export const Button2 = styled(Button1)`
color: skyblue;
`

jsx代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import React from "react";
import { Children } from "react";
import { AppWrapper, Button1, Button2} from "./style";
//编写组件
class App extends React.PureComponent{
constructor(){
super()
}
render(){
return (
<AppWrapper>
<Button1>父Button</Button1>
<Button2>子Button</Button2>
</AppWrapper>
)
}
}
export default App

image-20230329184407490

image-20230329184548981