React—10—过渡动画;React使用CSS的几种方式;React如何给元素动态添加类;
一、react-transition-grou过渡动画
react-transition-group本质是自动给我们添加类和删除类,具体的过渡动画效果还是要我们自己写。
◼ 在开发中,我们想要给一个组件的显示和消失添加某种过渡动画,可以很好的增加用户体验。
◼ 当然,我们可以通过原生的CSS来实现这些过渡动画,但是React社区为我们提供了react-transition-group用来完成过渡动画。
◼ React曾为开发者提供过动画插件 react-addons-css-transition-group,后由社区维护,形成了现在的 react-transition
group。
这个库可以帮助我们方便的实现组件的 入场 和 离场 动画,使用时需要进行额外的安装:
◼ react-transition-group本身非常小,不会为我们应用程序增加过多的负担。
react-transition-group介绍
# npm
npm install react-transition-group --save
◼ react-transition-group主要包含四个组件:
◼ Transition
该组件是一个和平台无关的组件(不一定要结合CSS);
在前端开发中,我们一般是结合CSS来完成样式,所以比较常用的是CSSTransition;
◼ CSSTransition
在前端开发中,通常使用CSSTransition来完成过渡动画效果
◼ SwitchTransition
两个组件显示和隐藏切换时,使用该组件
◼ TransitionGroup
将多个动画组件包裹在其中,一般用于列表中元素的动画;
(一)CSSTransition组件
1.1 CSSTransition是基于Transition组件构建的:
1.2CSSTransition执行过程中,有三个状态:appear、enter、exit;
这三个状态,又都有三种情况,需要定义对应的CSS样式:
- 第一类,开始状态:对于的类是-appear、-enter、exit;
- 第二类:执行动画:对应的类是-appear-active、-enter-active、-exit-active;
- 第三类:执行结束:对应的类是-appear-done、-enter-done、-exit-done;
appear appear是初次显示动画,和enter的区别是只有第一次显示会走apper,后面的显示都走enter。 enter enter是元素显示的动画,即进入动画,进入有三个状态,初始的enter、执行动画期间的enter-active、执行结束后的enter-done/ 并且react是给元素先加入enter类,在加入enter-active类, 最终经过我们写的timeout时间后,把enter和enter-active都去掉,加入enter-done类。 所以,如果我们想实现一个隐入隐出的效果, 可以在enter类里写opacity:0 然后react会立马在enter类保留的基础上,在添加一个enter-acitve类,这个时候enter-acitve类就写 opacity:1; transition:all 2s ease; 这样,这个元素的opacity属性就从0变到了1,然后由于我们加了一个transition的效果,所以opacity在变化的时候,会有动态效果。 最终在经过timeout时间后,react会把enter和enter-active类都去掉,然后加入enter-done类。 exit exit是元素消失的动画 用法和enter一样。
import React, { PureComponent } from 'react'; import { CSSTransition } from 'react-transition-group'; import './style.css'; // 编写一个组件 class App extends PureComponent { constructor() { super(); this.state = { isShow: true }; } render() { const { isShow } = this.state; return ( <div> <button onClick={e => this.setState({ isShow: !isShow })}>切换</button> <CSSTransition in={isShow} appear classNames="foo" timeout={2000} unmountOnExit={true}> <div> <h1>过渡动画</h1> </div> </CSSTransition> </div> ); } } export default App;
样式:::::::::::::::::::::::::
.foo-appear {
transform: translateX(-150px);
}
.foo-appear-active {
transform: translateX(0);
transition: transform 2s ease;
}
.foo-enter{
opacity: 0;
}
.foo-enter-active{
opacity: 1;
transition: all 1s ease;
}
.foo-exit{
opacity: 1;
}
.foo-exit-active{
opacity: 0;
transition: all 1s ease;
}
1.3CSSTransition常见对应的属性:
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:过渡动画的时间
appear:是否在初次进入添加动画(需要和in同时为true)
unmountOnExit:退出后是否卸载组件
其他属性可以参考官网来学习:https://reactcommunity.org/react-transition-group/transition
1.4 CSSTransition对应的钩子函数:
主要为了检测动画的执行过程,来完成一些JavaScript的操作
onEnter:在进入动画之前被触发;
onEntering:在应用进入动画时被触发;
onEntered:在应用进入动画结束后被触发;
(二)SwitchTransition
CSSTransition:一个是单独组件的显示和消失。
SwitchTransition:一个两个组件的切换。
◼ SwitchTransition可以完成两个组件之间切换的炫酷动画:
比如我们有一个按钮需要在on和off之间切换,我们希望看到on先从左侧退出,off再从右侧进入;
这个动画在vue中被称之为 vue transition modes;
react-transition-group中使用SwitchTransition来实现该动画;
◼ SwitchTransition中主要有一个属性:mode,有两个值
in-out:表示新组件先进入,旧组件再移除;
out-in:表示就组件先移除,新组建再进入;
◼ 如何使用SwitchTransition呢?
SwitchTransition组件里面要有CSSTransition或者Transition组件,不能直接包裹你想要切换的组件;
SwitchTransition里面的CSSTransition或Transition组件不再像以前那样接受in属性来判断元素是何种状态,取而代之的是
key属性;
(三)TransitionGroup
CSSTransition:单独组件切换(显示和消失)
SwitchTransition:两个组件的切换。
TransitionGroup:一组组件中,增加或删除某个组件。
二、React如何使用CSS
◼ 前面说过,整个前端已经是组件化的天下:
而CSS的设计就不是为组件化而生的,所以在目前组件化的框架中都在需要一种合适的CSS解决方案。
◼ 在组件化中选择合适的CSS解决方案应该符合以下条件:
可以编写局部css:css具备自己的具备作用域,不会随意污染其他组件内的元素;
可以编写动态的css:可以获取当前组件的一些状态,根据状态的变化生成不同的css样式;
支持所有的css特性:伪类、动画、媒体查询等;
编写起来简洁方便、最好符合一贯的css风格特点;
等等...
◼ 事实上,css一直是React的痛点,也是被很多开发者吐槽、诟病的一个点。
◼ 在这一点上,Vue做的要好于React:
Vue通过在.vue文件中编写 <style><style> 标签来编写自己的样式;
通过是否添加 scoped 属性来决定编写的样式是全局有效还是局部有效;
通过 lang 属性来设置你喜欢的 less、sass等预处理器;
通过内联样式风格的方式来根据最新状态设置和改变css;
等等...
◼ Vue在CSS上虽然不能称之为完美,但是已经足够简洁、自然、方便了,至少统一的样式风格不会出现多个开发人员、多个项目
采用不一样的样式风格。
◼ 相比而言,React官方并没有给出在React中统一的样式风格:
由此,从普通的css,到css modules,再到css in js,有几十种不同的解决方案,上百个不同的库;
大家一致在寻找最好的或者说最适合自己的CSS方案,但是到目前为止也没有统一的方案;
2.1内联样式
◼ 内联样式是官方推荐的一种css样式的写法:
style 接受一个采用小驼峰命名属性的 JavaScript 对象,而不是 CSS 字符串;
并且可以引用state中的状态来设置相关的样式;
◼ 内联样式的优点:
1.内联样式, 样式之间不会有冲突
2.可以动态获取当前state中的状态
◼ 内联样式的缺点:
1.写法上都需要使用驼峰标识
2.某些样式没有提示
3.大量的样式, 代码混乱
4.某些样式无法编写(比如伪类/伪元素)
◼ 所以官方依然是希望内联合适和普通的css来结合编写;
2.2普通CSS
◼ 普通的css我们通常会编写到一个单独的文件,之后再进行引入。
◼ 这样的编写方式和普通的网页开发中编写方式是一致的:
如果我们按照普通的网页标准去编写,那么也不会有太大的问题;
但是组件化开发中我们总是希望组件是一个独立的模块,即便是样式也只是在自己内部生效,不会相互影响;
但是普通的css都属于全局的css,样式之间会相互影响;
◼ 这种编写方式最大的问题是样式之间会相互层叠掉
2.3CSS modules
◼ css modules并不是React特有的解决方案,而是所有使用了类似于webpack配置的环境下都可以使用的。
如果在其他项目中使用它,那么我们需要自己来进行配置,比如配置webpack.config.js中的modules: true等。
◼ React的脚手架已经内置了css modules的配置:
.css/.less/.scss 等样式文件都需要修改成 .module.css/.module.less/.module.scss 等;
之后就可以引用并且进行使用了;
◼ css modules确实解决了局部作用域的问题,也是很多人喜欢在React中使用的一种方案。
◼ 但是这种方案也有自己的缺陷:
引用的类名,不能使用连接符(.home-title),在JavaScript中是不识别的;
所有的className都必须使用{style.className} 的形式来编写;
不方便动态来修改某些样式,依然需要使用内联样式的方式;
◼ 如果你觉得上面的缺陷还算OK,那么你在开发中完全可以选择使用css modules来编写,并且也是在React中很受欢迎的一种方式。
2.4 CSS in JS
◼ 官方文档也有提到过CSS in JS这种方案:
“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
2.5 css in js的重点框架, styled-components
◼ 批评声音虽然有,但是在我们看来很多优秀的CSS-in-JS的库依然非常强大、方便:
CSS-in-JS通过JavaScript来为CSS赋予一些能力,包括类似于CSS预处理器一样的样式嵌套、函数定义、逻辑复用、动态修
改状态等等;
虽然CSS预处理器也具备某些能力,但是获取动态状态依然是一个不好处理的点;
所以,目前可以说CSS-in-JS是React编写CSS最为受欢迎的一种解决方案;
◼ 目前比较流行的CSS-in-JS的库有哪些呢?
styled-components
emotion
glamorous
◼ 目前可以说styled-components依然是社区最流行的CSS-in-JS库,所以我们以styled-components的讲解为主;
◼ styled-components的本质是通过函数的调用,最终创建出一个组件:
- 这个组件会被自动添加上一个不重复的class;
- styled-components会给该class添加相关的样式;
◼ 另外,它支持类似于CSS预处理器一样的样式嵌套:
- 支持直接子代选择器或后代选择器,并且直接编写样式;
- 可以通过&符号获取当前元素;
- 直接伪类选择器、伪元素等;
2.6 styled-components的props属性和attrs属性
import React, { PureComponent } from 'react'; import { AppWrapper, PartWrapper, DefaultWrapper } from './style'; // 编写一个组件 class App extends PureComponent { constructor() { super(); this.state = { isShow: true, fontSize: '32px', color: 'skyBlue' }; } render() { const { isShow, fontSize, color } = this.state; return ( <div> <button onClick={e => this.setState({ isShow: !isShow })}>切换</button> <AppWrapper> <h1 className="head">头部</h1> <div className="body">body</div> <footer> 脚{/* 给样式组件传递一些变量 */} <PartWrapper fontSize={fontSize} color={color}> <div className="section"> <div>1</div> <div>2</div> <div>3</div> </div> </PartWrapper> <DefaultWrapper color2={color}> <div className="section2">section2</div> <div className="section3">section3</div> </DefaultWrapper> </footer> </AppWrapper> </div> ); } } export default App;
import styled from 'styled-components'; export const AppWrapper = styled.div` .head { color: red; } .body { background-color: #f2f2f2; &:hover { background-color: skyblue; } } footer { color: blue; } `; export const PartWrapper = styled.div` .section { width: 100px; height: 50px; margin: 0 auto; color: ${props => props.color}; font-size: ${props => props.fontSize}; border: 1px solid skyblue; display: flex; flex-direction: row; flex-wrap: nowrap; justify-content: space-around; align-items: center; } `; // attrs属性,可以给组件添加属性,这样除了父组件穿的propos属性,还有自己定义的属性。 // color2属性: 可以先判断父组件里是否有传值,有则取父组件传的值,没有则默认给值。 // color3属性: 直接给默认值 export const DefaultWrapper = styled.div.attrs(props => ({ color2: props.color2 || 'red', color3: '#fff' }))` .section2 { color: ${props => props.color2}; } .section3 { color: ${props => props.color3}; } `;
三、React动态给元素添加class
第一步: npm install classNames
第二步:
import React, { PureComponent } from 'react'; import classNames from 'classnames'; // 编写一个组件 class App extends PureComponent { constructor() { super(); this.state = { isFoo: true }; } render() { const { isFoo } = this.state; return ( <div> <h1 className={classNames({ foo: isFoo })}>头部</h1> </div> ); } } export default App;
分类:
3.前端框架
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
2024-03-03 SpringBoot—01—简介;基本使用;