• react总结之css样式和动画


      事实上react官方并没有关于样式写法的统一说法,能在react中使用样式的方法有很多,下面分别来介绍以下几种:

      一、内联样式

      style接受一个采用驼峰命名属性的js对象,而不是css字符串,它可以引用state中的状态来设置相关样式,是一种最基本的写法。内联样式中,样式之间不会有冲突,但是所有的写法都需要使用小驼峰标识,这样的写法在代码中存在的大量的样式,看起来十分的混乱,而且像伪类,伪元素它们是无法进行编写的。

    import React from 'react'
    import ReactDOM from 'react-dom'
    class App extends React.Component {
        constructor(props) {
            super(props);
            this.state = { color: "purple" }
        }
        render() {
            const divStyle = {
                //动态的来获取
                color: this.state.color,
                textDecoration: "underline"
            }
            return (
                <>
                    <div style={{ color: 'lightblue', fontSize: '20px' }}>行内样式</div>
                    <div style={divStyle}>可以用到state</div>
                </>
            )
        }
    }
    ReactDOM.render(<App />, document.getElementById('root'))

      二、引入样式

      即把css样式写到一个单独文件,之后再进行引入。这种方式和网页开发中编写方式是一致的,我们比较熟悉,但是这种写法样式之间会相互影响存在相互层叠的风险。

    // css文件
    .common{
        color: purple;
        text-decoration: underline;
    }
    
    // index.js文件
    import React from 'react'
    import ReactDOM from 'react-dom'
    import './style.css'
    class App extends React.Component { 
        render() {  
            return (
                <>
                    <div className='common'>普通css引入</div>
                </>
            )
        }
    }
    ReactDOM.render(<App />, document.getElementById('root'))

      三、css Modules

      这一种方式它主要是利用配置将.css文件进行编译,编译后在每个使用css的地方,css类名都是独一无二,不会和其它的冲突。css Modules它并不是react中特有的解决方案,而是所有使用了类似于webpack配置环境下都可以使用。react的脚手架已经内置了css Modules的配置即:.css/.less等样式文件都修改成了.module.css/.module.less。但如果在其它的项目中使用css Modules就需要我们自己来配置webpack.config.js将其中的modules设置为true。

    // App-style.module.css文件  一定要注意名称后.module
    .color{
        color: lightblue;
      }
    // demo.js文件
    import React from 'react'
    import ReactDOM from 'react-dom'
    import  appStyle from './App-style.module.css'
    class App extends React.Component { 
        render() {  
            return (
                <>  
                    <h2 className={appStyle.color}>我是App组件</h2>
                </>
            )
        }
    }
    ReactDOM.render(<App />, document.getElementById('root'))

      但这种方式也有其自身的局限性,引用类名时不能使用连接符,如.app-style,它在js中是不识别的;所有的className都要用到className={style.className}的形成来编写,也不能动态的修改某些样式,依然还是要使用到内联样式。但是这种方法解决了局部作用域的问题,也有很多人喜欢用这种方式编写css。 

      四、styled Components

      说到styled Components第三方库首先要提的是“CSS-in-JS”。指的是一种模式,它是将css也写入到js中而不是在外部文件中定义。在传统的前端开发中,我们奉行结构,样式,逻辑三者相分离,随着前端开发日益复杂,组件化思想,在react中它认为逻辑本身和UI无法分离,样式也属于UI的一部分,所以有了all in js的思想,虽然这样思想受到了许多的批评,但有一些css-in-js库,其功能十分方便,强大,其中最为出名的就是styled-components,其它的还有emotion、glamorous等。

      使用styled-components。由于它是第三方库,在react官方中并没有定义,所以使用前必须安装: yarn add styled-components。它本质上是通过函数的调用创建出一个组件,这个组件会被添加上一个不重复的class,styled-components会给这个class添加上相应的样式。它主要运用了带标签的模板字符串的相关知识,在正常情况下我们都是通过函数名()的方式对函数进行调用,但还可以通过模板字符串(``)对函数进行调用,如果我们在调用时插入了其它的变量,那模板字符串被拆分了,标签函数的第一个参数是被模板字符串拆分的字符串组合的数组,其它元素是模板字符串传入的内容。

        function getPerInfo(part1, part2, part3) {
          console.log(part1, part2, part3); //[" my name is ", " , ", " years old", raw: Array(3)] "davina" 20
        }
        const person = 'davina',
              age = 20;
        getPerInfo` my name is ${person} , ${age} years old`
    // StyledComponent.js文件
    
    //使用步骤:1.导入 名字可以随便的起这里是styled
    import styled, { isStyledComponent } from 'styled-components';
    //这里进行导出,在demo.js里使用,主要用到的标签模板字符串相关知识
    export const DemoWrapperDiv = styled.div`
        height:300px;
        300px;
        background:pink;
        /* 1.可以进行样式的嵌套 */
        span{
            color:yellow;
            /* 2.&的使用,表示即是span元素也要有active属性 */
            &.active{
                color:white;
            }
        }
    `
    export const DemoWrapperH3 = styled.h3`
        color:red;
        /* 3.可以添加伪类,伪元素 */
        &:hover{
            color:orange;
            font-size:20px;
        }
        &::after{
            content: "好看"
        }
    `
    //  4.attrs是一个函数,它传入一个对象,返回一个函数
    export const StyledInput = styled.input.attrs({
        placeholder: "百度一下",
        bColor: '#c6c9cb',
    })`
      background-color: lightblue;
          /* 5.props具有穿透性  */
      border-color: ${props => props.bColor};
      /* 6.动态设置css样式 */
      color: ${props => props.color}; 
    `
    export const StyledButton = styled.button`
        color:pink;
        margin:5px;
        background:lightblue;
        border:2px solid #a9a9ee;
    `
    // 7.styled-components具有继承性
    export const StylePrimaryButton = styled(StyledButton)`
        color:purple;
        /* 8.可以使用共享 */
        font-size:${props=>props.theme.fontSize};
    `
    // demo.js文件
    import React from 'react'
    import ReactDOM from 'react-dom'
    import { DemoWrapperDiv, DemoWrapperH3, StyledInput, StyledButton, StylePrimaryButton } from './styledComponents'
    import { ThemeProvider } from 'styled-components';
    class App extends React.Component {
        constructor(props) {
            super(props);
            this.state = { color: "seagreen" }
        }
        render() {
            return (
                // 2.进行使用
                // 使用ThemeProvider设置主题
                <ThemeProvider theme={{ fontSize: '16px' }}>
                    <DemoWrapperDiv>
                        <DemoWrapperH3>使用styled-components</DemoWrapperH3>
                        <span>样式嵌套1</span><br />
                        <span className="active">样式嵌套2</span><br />
                        <DemoWrapperH3 >支持伪类</DemoWrapperH3>
                        < StyledInput
                            style={{ height: '25px',  '200px' }}
                            // 传入state作为props属性,结合上文可动态修改css样式 
                            color={this.state.color} /><br />
                        <StyledButton>button</StyledButton>
                        <StylePrimaryButton>primary button</StylePrimaryButton>
                    </DemoWrapperDiv>
                </ThemeProvider>
            )
        }
    }
    ReactDOM.render(<App />, document.getElementById('root'))

      五、 classnames库

       react中添加class用到className来代替class,除了className还可以用到classnames这个第三方库,classnames它其实是一个函数,用它可以很方便为元素添加class属性,动态的判断是否为组件添加类名。它是一个第三方库,使用前要先进行安装 yarn add classnames/npm i classnames --save。使用方式如下:

    import React, { PureComponent } from 'react'
    import classNames from 'classnames'
    export default class App extends PureComponent {
        constructor(props) {
            super(props)
            this.state = {
                isActive: true,
            }
        }
        render() {
            let isActive = this.state,
                isBar = false,
                errClass = 'error',
                warnClass = 0;//注意后面如果加上的是undefined,null,0时,不会添加
            return (
                <div>
                    {/* 原生React中添加class方法 */}
                    {/* 使用运算符,进行字符串拼接,要注意空格的问题 */ }
                    <h2 className={"title " + (isActive ? "active" : "")}>我是标题2</h2>
                    <h2 className={["title", (isActive ? "active" : "")].join(" ")}>我是标题3</h2>
    
                    {/* classnames库添加class */}
                    {/* 直接进行调用,它返回的是一个字符串 */}
                    <h2 className={classNames("foo", "bar", "active", "title")}>我是标题</h2>
    
                    {/* 它后面可以加上一个对象(键值对),后面也可以加上对象 */}
                    <h2 className={classNames({ "active": isActive, "bar": isBar }, "title")}>我是标题</h2>
    
                    {/* 把多个传入的东西,写到一起 */}
                    <h2 className={classNames("foo", errClass, warnClass, { "active": isActive })}>我是标题</h2>
                    {/* 数组 */}
                    <h2 className={classNames(["active", "title"])}>我是标题</h2>
                    <h2 className={classNames(["active", "title", { "bar": isBar }])}>我是标题</h2>
                </div>
            )
        }
    }

      六、react中的动画

      在开发中,如果我们想要给组件增加用户体验,添加某些过渡动画,除了原生css实现方式以外,还有react-transition-group。它应用的比较广泛,当然还有一些其它不错的库,如react-spring。

      react-transition-group是react社区提供用于实现组件进入和退出等较简单动画,使用时需要额外进行安装yarn add react-transition-group/npm i react-transition-group --save。它主要包含Transition,CSSTransition,SwitchTransition,TransitionGroup这四个组件。下面来分别进行介绍:

      1 、Transition&CSSTransition

      在实际的开发中一般要结合css完成样式,常用CSSTransition来完成过渡的动画效果。CSSTransition是基于Transition进行构建,所以我们可以一起进行学习探索。

      CSSTransition在执行的过程中有三种开始状态即appear(开始)、enter(进入)、exit(退出)。这三种状态分别要有对应的CSS样式。开始状态:-apper、-enter、-exit;执行动画:-apper-active、-enter-active、-exit-active;执行结束:-appear-done、-enter-done、-enter-done。如下案例所示,点击按钮时,给图片增加动画,让图片从显示与隐藏之间进行切换且图片大小和透明度进行变化。要注意CSSTransition相关属性的应用,它有一系列的钩子函数,可以更加方便检测动画执行的过程,还可以用来完成一些其它js操作。

    // demo.js
    import ReactDOM from 'react-dom'
    import React, { PureComponent } from 'react'
    //1.安装并引入
    import { CSSTransition } from 'react-transition-group';
    import './CSSTransition.css'
    class App extends PureComponent {
        constructor(props) {
            super(props)
            this.state = {
                src: 'https://d33wubrfki0l68.cloudfront.net/0834d0215db51e91525a25acf97433051f280f2f/c30f5/img/redux.svg',
                isShow: true
            }
        }
        render() {
            const { src, isShow } = this.state;
            return (
                <div>
                    <button onClick={e => this.setState({ isShow: !isShow })}>显示/隐藏</button>
                    <br />
                    {/* 2.在需要用到的地方进行使用,给CSSTransition设置相对应的属性 */}
                    <CSSTransition
                        //in:触发进入或者退出状态,一般为布尔值,为true时,触发进入状态,为false时触发退出状态
                        in={isShow}
                        // classNames:动画名称,如后文img-enter-active等,要和style中样式的开头保持一致
                        classNames='img'
                        // timeout:过渡时间
                        timeout={300}
                        // appear:是否在初次进入添加动画(需和in都为true)
                        appear
                        // unmountOnExit:退出后卸载组件,这样不占位置
                        unmountOnExit={true}
                        //下面是生命周期钩子
                        onEnter={el => console.log("开始进入")}
                        onEntering={el => console.log("正在进入")}
                        onEntered={el => console.log("进入完成")}
                        onExit={el => console.log("开始退出")}
                        onExiting={el => console.log("退出状态")}
                        onExited={el => console.log("退出完成")}>
                        <img src={src} style={{  '200px', height: '200px' }}></img>
                    </CSSTransition>
                </div>
            )
        }
    }
    ReactDOM.render(<App />, document.getElementById('root'));
    /* CSSTransition.css */ /* 刚开始进入,入场动画 */ .img-enter, .img-appear {opacity: 0;transform: scale(.8);} .img-enter-active, .img-appear-active { opacity: 1;transform: scale(1); /* 下面的时间是控制css的时间的 */ transition: opacity 300ms, transform 300ms;} .img-enter-done, .img-appear-done {opacity: 1;} /* 出场动画 */ .img-exit {opacity: 1;transform: scale(1);} .img-exit-active {opacity: 0;transform: scale(.8);transition: opacity 300ms, transform 300ms;} .img-exit-done {opacity: 0;}

      2、 SwitchTransition

      它可以完成两个组件之间切换的动画。在使用时它主要有一个属性需要特别的注意即mode分别对应两个值in-out/out-in,SwitchTransition组件里面要有CSSTransition或者是Transition组件,这两个组件不能像之前一样用in属性来判断元素是何种状态,而是要用key属性。如下例所示:按钮内容在on/off来回切换,并伴随有透明度和位置的动画。

    // demo.js
    import ReactDOM from 'react-dom'
    import React, { PureComponent } from 'react'
    //1.安装并引入
    import { SwitchTransition, CSSTransition } from 'react-transition-group'
    import './SwitchTransition.css'
    class App extends PureComponent {
        constructor(props) {
            super(props)
            this.state = {
                isOn: true
            }
        }
        render() {
            const { isOn } = this.state;
            return (
                <div>
                    {/* 要注意这里的mode:in-out:新组件先进入,旧组件再移除 out-on:旧组件先移除,新组件再进入 */}
                    <SwitchTransition mode='out-in'>
                        <CSSTransition
                            // key是来判断元素是显示或者是隐匿
                            key={isOn ? 'on' : 'off'}
                            classNames="btn"
                            timeout={500} >
                            <button onClick={e => this.setState({ isOn: !isOn })}
                                style={{ background: 'lightblue' }}
                            >{isOn ? "on" : "off"}</button>
                        </CSSTransition>
                    </SwitchTransition>
                </div>
            )
        }
    }
    ReactDOM.render(<App />, document.getElementById('root'));
    
    /* SwitchTransition.css */
    .btn-enter {opacity: 0; transform: translateX(100%);}
    .btn-enter-active {opacity: 1; transition: opacity 500ms,transform 500ms; transform: translateX(0) ;}
    .btn-exit {opacity: 1; transform: translateX(0);}
    .btn-exit-acitive {opacity: 0; transition: opacity 500ms,transform 500ms; transform: translateX(-100%);}

      3、TransitionGroup

      当我们有一组动画,需要将这些CSSTransition放到TransitionGroup来中完成。

    // demo.js
    import ReactDOM from 'react-dom'
    import React, { PureComponent } from 'react'
    import { CSSTransition, TransitionGroup } from 'react-transition-group'
    import './TransitionGroup.css'
    class App extends PureComponent {
        constructor(props) {
            super(props)
            this.state = {
                books: ['革命时期的爱情', '一只特立独行的猪', '黄金时代', '白银时代']
            }
        }
        render() {
            return (
                <div>
                    <TransitionGroup>
                        {
                            this.state.books.map((item, index) => {
                                return (
                                    <CSSTransition key={index} timeout={500} classNames='book'>
                                        <div>{item}</div>
                                    </CSSTransition>
                                )
                            })
                        }
                    </TransitionGroup>
                    <button onClick={e => this.setState({ books: [...this.state.books, '青铜时代'] })}>click</button>
                </div>
            )
        }
    }
    ReactDOM.render(<App />, document.getElementById('root'));
    /* TransitionGroup.css */ .book-enter {opacity: 0; transform: scale(.6);} .book-enter-active {opacity: 1; transform: scale(1); transition: opacity 300ms, transform 300ms;} .book-enter-done {color: lightpink;} .book-exit {opacity: 1; transform: scale(1);} .book-exit-active {opacity: 0;transform: scale(.6);transition: opacity 300ms, transform 300ms;} .book-exit-done {opacity: 0;}

     

      

     

  • 相关阅读:
    Linux下使用curl查看http请求各阶段耗时
    yum list查看版本
    【k8s】XX 修改ipvs模式
    域名访问时间 测试脚本
    关闭WINDOWS自动检测互联网络
    win10专业版安装VMware workstation pro 16时提示“setup failed to generate the ssl keys necessary to run vmware”笔记
    手动启动MegaRAID Storage Manager v17.05.02.01 for Linux
    Java基于POI实现excel任意多级联动下拉列表——支持从数据库查询出多级数据后直接生成【附源码】
    C# 后台POST数据及API接收简记
    Linux 安装pycharm,清除缓存,scp传输文件
  • 原文地址:https://www.cnblogs.com/davina123/p/13802761.html
Copyright © 2020-2023  润新知