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;
复制代码

 

posted @   Eric-Shen  阅读(5)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
历史上的今天:
2024-03-03 SpringBoot—01—简介;基本使用;
点击右上角即可分享
微信分享提示