React样式
第一节、React的过渡动画
Section titled “第一节、React的过渡动画”react-transition-group介绍
Section titled “react-transition-group介绍”React曾为开发者提供过动画插件 react-addons-css-transition-group,后由社区维护,形成了现在的 react-transition-group。
可以通过原生的CSS来实现这些过渡动画,但是**
React社区为我们提供**了react-transition-group用来完成过渡动画。
-
帮助实现组件的 ”入场“ 和 ”离场“ 动画,由于是社区在维护,需要安装使用
Terminal window npm install react-transition-group --save -
优点:
react-transition-group本身非常小,不会为我们应用程序增加过多的负担
react-transition-group主要组件
Section titled “react-transition-group主要组件”-
react-transition-group主要包含四个组件:Transition该组件是一个和平台无关的组件(不一定要结合CSS); 在前端开发中,我们一般是结合CSS来完成样式,所以比较常用的是CSSTransition;CSSTransition在前端开发中,通常使用CSSTransition来完成过渡动画效果SwitchTransition两个组件显示和隐藏切换时,使用该组件TransitionGroup将多个动画组件包裹在其中,一般用于列表中元素的动画;
-
总结:
CSSTransition就是基于Transition组件构建的,所以使用后三个即可
一、CSSTransition
Section titled “一、CSSTransition”- CSSTransition执行过程中,有三个状态:
appear:页面首次加载的时候enter:动画过渡前exit:动画结束后- 关键字,
active和done
1》状态所对应的CSS样式
Section titled “1》状态所对应的CSS样式”- 开始状态:对应的类是
-appear、-enter、exit; - 执行动画:对应的类是
-appear-active、-enter-active、-exit-active; - 执行结束:对应的类是
-appear-done、-enter-done、-exit-done;
2》CSSTransition 组件的属性
Section titled “2》CSSTransition 组件的属性”- 注意:
CSSTransition只允许有一个根,
import {CSSTransition, SwitchTransition, TransitionGroup} from 'react-transition-group' render() { const {isShow} = this.state return ( <div> <button onClick={e => this.setState({isShow: !isShow})}>trigger</button> <CSSTransition //class前缀 classNames="wyn" //判断是否显示 in={isShow} //当被Switch和group包裹的时候 key 会代替in属性的作用 //key={isShow ? 1: 2} //首次渲染的是否添加动画 appear={true} //是否卸载组件,不使用的话需要添加 done class // unmountOnExit={true} //class 切换完成的时间 timeout={2000} > {/*只允许有一个根*/} <div className="box"> <h4>张三</h4> <h4>李四</h4> </div> </CSSTransition> </div> ) }1、in触发进入或者退出状态 unmountOnExit
Section titled “1、in触发进入或者退出状态 unmountOnExit”简单说:给
in属性绑定一个boolean变量,来控制显示隐藏,
-
重点:需要搭配
unmountOnExit={true}属性使用 之后CSSTransition会自动卸载组件否则组件不卸载,动画结束后还会回显
- 如果频繁切换,不希望组件卸载的话,可以使用
enter/exit-doneclass
- 如果频繁切换,不希望组件卸载的话,可以使用
-
-
当
in为true时,触发进入状态,会添加-enter、-enter-acitve的class开始执行动画,当动画执行结束后,会移除两个class,并且添加-enter-done的class;\ -
当
in为false时,触发退出状态,会添加-exit、-exit-active的class开始执行动画,当动画执行结束后,会移除两个class,并且添加-enter-done的class;
-
2、classNames属性动画class的前缀
Section titled “2、classNames属性动画class的前缀”确定
classNames之后,对应的class名称:比如card-enter、card-enter-active、card-enter-done;
3、timeout:过渡动画的时间
Section titled “3、timeout:过渡动画的时间”-
过渡动画
class的持续实现,在其属性指定的时间内完成class的切换 -
区分
Transition中的duration:timeout:是在指定的时间内,要完成对应class的切换duration:是动画的持续时间,有可能动画结束了,timeout时间常的话可能动画结束一段时间在进行active的切换
4、appear
Section titled “4、appear”是否在初次进入添加动画(需要和in同时为true)
5、CSSTransition对应的钩子函数
Section titled “5、CSSTransition对应的钩子函数”主要为了检测动画的执行过程,来完成一些JavaScript的操作
onEnter:在进入动画之前被触发;onEntering:在应用进入动画时被触发;onEntered:在应用进入动画结束后被触发;
6、注意:react-transtion-group 中没有 move移动class
Section titled “6、注意:react-transtion-group 中没有 move移动class”需要手动实现,利用
height属性
.wyn-enter,.wyn-appear { opacity: 0; /* height: 23px; */}.wyn-enter-active,.wyn-appear-active { opacity: 1; /* height: 0; */ transition: all 2s ease;}
.wyn-enter-done { display: block;}.wyn-exit-done { display: none;}
.wyn-exit { opacity: 1; /* height: 23px; */}
.wyn-exit-active { opacity: 0; /* height: 0; */ transition: all 2s ease; /* position: absolute; */
}
.move {
transition: all 2s ease;}二、SwitchTransition
Section titled “二、SwitchTransition”结合
CSSTransition组件实现元素之间的切换。
- 知识点:与
CSSTransition元素进行切换的区别,就是有mode属性 - 而
vue中将该属性都会在,Transition组件中
1、Mode属性
Section titled “1、Mode属性”字符串类型,必填
in-out:表示新组件先进入,旧组件再移除;out-in:表示就组件先移除,新组建再进入;
2、使用SwitchTransition
Section titled “2、使用SwitchTransition”-
注意:
SwitchTransition要和CSSTransition组件一起使用,不能单独使用SwitchTransition包裹的CSSTransition组件 -
Transition中 key属性:SwitchTransition包裹的CSSTransition或Transition组件不再像以前那样接受in属性来判断元素是何种状态,取而代之的是key属性;
render() { const {isShow} = this.state return ( <div> <h3>SwichTransition</h3> <button onClick={e => this.setState({isShow: !isShow})}>trigger</button> <SwitchTransition mode="in-out"> <CSSTransition classNames={"wyn"} key={isShow ? 1 : 2} timeout={2000} unmountOnExit={true}> { isShow ? <h5>张三</h5> : <h5>李四</h5> } </CSSTransition> </SwitchTransition> </div>
) }三、TransitionGroup
Section titled “三、TransitionGroup”
CSSTransition只能给一个根元素添加过渡动画
-
在
react-transition-group需要使用TransitionGroup组件包裹多个CSSTransition组件来实现批量添加动画 -
vue中 只需要transition-group组件直接包裹即可
component 属性
Section titled “component 属性”类似
vue中transition-group组件中的tag属性,TransitionGroup,同样不是容器,可以通过component渲染成指定的元素
print() { const {books} = this.state let temp = books.map((item, index) => ( <CSSTransition classNames={"wyn"} key={item.id} timeout={2000}> <li className='move'> <span className="span">{item.name}</span>-- <span className="span">{item.price+"$"}</span> <button onClick={e => this.del(e, index)}>del</button> </li> </CSSTransition> )) return temp }
render() { return ( <div> <h4>transitionGroup</h4> <TransitionGroup component={"ul"}> {this.print()} </TransitionGroup> </div> ) }第二节、react编写css
Section titled “第二节、react编写css”在 react 中,没有 css 作用域
一、内联样式CSS写法
Section titled “一、内联样式CSS写法”
react官方文档中的写法。
- 对象写法
style属性绑定样式对象
export class App extends PureComponent { constructor() { super() this.state = { temp: { border: "2px solid red", fontSize: "24px" } } } render() { return ( <div> <h4>内联样式</h4> <div className="container"> <div className="box" style={this.state.temp}> <h5>这里是张三</h5> </div> </div> </div> ) }}二、普通CSS文件写法
Section titled “二、普通CSS文件写法”- 注意:普通的
class文件的写法,是没有class作用域的 - 因此无论在哪加载的
class都是全局的css样式
2.1、React 中使用less
Section titled “2.1、React 中使用less”react 中是没有默认配置less 对应loader 的,同时有不对外展示配置文件,因此需要通过第三方插件,来进行手动配置
-
ant.design UI框架有教程直接安装,
craco-lessTerminal window npm i craco-less
翻译过来就是, create-react-app-config 插件
@craco/craco@alpha 内测版本
npm install @craco/craco-
将
package.json启动脚本命令修改为craco启动这样的话会自动帮忙合并
webpack配置"scripts": {"start": "set PORT=9000 && craco start","build": "craco build","test": "craco test","eject": "react-scripts eject"}, -
然后在项目根目录创建一个
craco.config.js用于修改默认配置。 -
配置好就可以直接导入使用了
2.2、css导入
Section titled “2.2、css导入”由于 React 框架使用的 jsx
- 因此也是没有
style的@import导入的关键字 - 只能使用模块化的导入方式 ,
require、import()异步导入 - 或者使用
Portal向header标签导入一个style元素
require("./style.less")//使用Portal render() { const el = <style >@import("./style.less")</style> const dom = document.querySelector("head") return createPortal(el, dom) }三、CSS Module写法
Section titled “三、CSS Module写法”
css modules并不是React特有的解决方案,而是所有使用了类似于webpack配置的环境下都可以使用的。
-
其他项目中使用需要手动配置
-
React的脚手架已经内置了css modules的配置,可以直接使用 -
通过这种方式可以让
css有自己的作用域 -
唯一不适应的就是,需要
css对象**.calss属性** 获取,这样就不能使用emmt语法了要将css文件当作模块对象进行导入
使用 CSS Module
Section titled “使用 CSS Module”需要将所有的
css文件,或者less文件修改为以module文件名结尾的文件
例:index.module.css
-
需要将
xxx.module.css文件当作模块对象导入默认是 default 导入,直接使用导入对象使用
import React, { PureComponent } from 'react'import app from "./index.module.less"export class App extends PureComponent {
render() { return( <div className="container"> {/*需要 css对象.calss属性 获取*/} <div className={app.box}> <h5 className='item'>这里是张三</h5> </div> </div> ) }}
export default App四、CSS in JS
Section titled “四、CSS in JS”官方文档也有提到过CSS in JS这种方案
- “CSS-in-JS” 是指一种模式,其中
CSS由JavaScript生成而不是在外部文件中定义- 因此
React有被人称之为All in JS
- 因此
- 此功能并不是
React的一部分,而是由第三方库提供
1、常见 CSS in JS的库
Section titled “1、常见 CSS in JS的库”-
styled-components:目前最流行的 CSS-in-JS库Terminal window npm install styled-components -
emotion:语法同styled-components差不多 -
glamorous
-
它支持类似于CSS预处理器一样的样式嵌套:
- 支持直接子代选择器或后代选择器,并且直接编写样式;
- 可以通过
&符号获取当前元素; - 直接伪类选择器、伪元素等;
-
官方提供了 编写css 的vscode插件
vscode-styled-components
3、styled-components的使用
Section titled “3、styled-components的使用”
styled-components是通过模板字符串调用的方式使用的
-
回顾:以
${}进行分,将差分的字符串数组集合当作第一参数传入,后续的${}会当作参数列表一次传入 -
根据这种调用方式生成
css样式styled-components的本质是通过函数的调用,最终创建出一个组件:- 这个组件会被自动添加上一个不重复的
class; styled-components会给该class添加相关的样式
- 这个组件会被自动添加上一个不重复的
-
非常简单,下载之后导入使用
import styled from 'styled-components'const ModuleCss = styled.div`.box {border: 3px solid salmon;}`render() {return (//直接使用创建的组件进行使用<ModuleCss><h4>modeule css</h4><div className="container"><div className="box"><h5 className='item'>这里是张三</h5></div></div></ModuleCss> )}
props属性、attrs方法
Section titled “props属性、attrs方法”可以更加灵活的,动态添加属性
-
props属性会传入到,${}包裹的形参中props属性会包含attrs()方法初始化的一些对象属性- 还会包含,在组件上自定义的一些属性
-
可以用通过
attrs()方法初始化一些css属性值在
arrts({})中定义的属性,通过props属性来获取- 参数:
Object||Function
- 参数:
//object 初始化一些属性 import styled from 'styled-components'; export const ModuleCss = styled.div.attrs({ num: 3 })` .box { border: ${props => props.num}px solid red; } `
//function设置props默认属性export const ModuleCss = styled.div.attrs(props => { return { num: 3, //设置默认值 title: props.title || "blue" } })` .box { border: ${props => props.num}px solid red; } `export const Bar = styled.div` border: 1px blue solid`//注意这例styled()方法后面要进行调用拼接模板字符串或者手动调用export const Foo = styled(Bar)``//export const Foo = styled(Bar)("")classnames库
Section titled “classnames库”在
jsx中,可以很灵活的使用js代码,进行条件判断动态添加所需要的类
-
但是在业务逻辑过多的情况下,冗长的三元匀速符,会在标签属性上占据过多控件,导致阅读性很差
-
可以借助第三方的库:
classnames可以像
vue中使用对象和数组动态的绑定class, 和vue中class绑定几乎一致 -
相对与vue的绑定,classnames 的优势就是是个函数,添加参数列表比较方便一点
-
下载
Terminal window npm install classnames -
使用
import React, { PureComponent } from 'react'import classNames from 'classnames'export class App extends PureComponent {return (<div>{/*既可以放入参数列表中,也能放在数组中*/}<h2 className={classNames("aaa", { bbb:isbbb, ccc:isccc })}>嘿嘿嘿</h2><h2 className={classNames(["aaa", { bbb: isbbb, ccc: isccc }])}>嘻嘻嘻</h2></div>)}}export default App
第三节、图片的导入
Section titled “第三节、图片的导入”- 在webpack 当中所有的,图片要使用模块,原因是,打包的时候会修改文件路径,在项目启动之后动态加载的时候,获取不到完整的文件名