Transition 包含 4 个状态
entering
entered
exiting
exited
props
nodeRef 执行动画的关联 DOM 节点, 早期的版本使用 findDOMNode(deprected) 查找 DOM 节点, 报错的替换方案
in 切换 enter 和 exit 的状态
appear 控制组件首次挂载时的默认行为
enter 控制进入的动画
exit 控制退出的动画
timeout 动画的时长
addEvenetListener 添加自定义的事件
onEnter
onEntering
onEntered
onExit
onExiting
onExited
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 import {useState, useRef} from 'react' ;import {Transition } from 'react-transition-group' ;function App ( ){ const [isProp, setInProp] = useState (false ); const nodeRef = useRef (null ); return ( <> <Transition nodeRef ={nodeRef} in ={inProp} timeout ={500} > <h2 > react-transition-group Transition component</h2 > </Transition > <button onClick ={() => setInProp(true)}>Click to Enter</button > </> ) }
CSSTransition 继承 Transition 的所有 props, 使用 CSS 设置动画
classNames 当组件在 appear, enter, exit 时应用于组件的动画名称前缀
classNames=”my-node” 将会应用以下几种样式
my-node-appear, my-node-appear-active, my-node-appear-done
my-node-enter, my-node-enter-active, my-node-enter-done
my-node-exit, my-node-exit-active, my-node-exit-done
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 import {useState, useRef} from 'react' ;import {CSSTransition } from 'react-transition-group' ;function App ( ){ const [inProp, setInProp] = useState (false ); const nodeRef = useRef (null ); return ( <> <CSSTransition nodeRef ={nodeRef} in ={inProp} timeout ={500} classNames ="my-node" > <div ref ={nodeRef} > react-transition-group CSSTransition component </div > </CSSTransition > <button onClick ={() => setInProp(true)}>Click to Enter</button > </> ) } <style> .my -node-enter, .my -node-appear { opacity : 0 ; } .my -node-enter-active, .my -node-appear-active { opacity : 1 ; transition : opacity 500ms; } .my -node-exit { opacity : 1 ; } .my -node-exit-active { opacity : 0 ; transition : opacity 500ms; } </style>
SwitchTransition 切换两个组件的动画, 需要使用 key 作为 Transition 或 CSSTransition 的 props
mode 动画的模式 in-out|out-in, 默认 out-in
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 import {useState, useRef} from 'react' ;import {SwitchTransition , CSSTransition } from 'react-transition-group' ;function App ( ){ const [state, setState] = useState (false ); const helloRef = useRef (null ); const goodByeRef = useRef (null ); const nodeRef = state ? goodByeRef : helloRef; return ( <SwitchTransition mode ="out-in" > <CSSTransition key ={state ? 'goodeBye , world ' : 'hello world '} nodeRef ={nodeRef} classNames ="fade" > <button ref ={nodeRef} onClick ={() => setState(state => !state)} > {state ? 'goodBye, world' : 'hello world'} </button > </CSSTransition > </SwitchTransition > ) }
TransitionGroup 管理多个动画列表
component 指定渲染的元素, 默认 div
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 import {useState} from 'react' ;import {TransitionGroup , CSSTransition } from 'raect-transition-group' ;function App ( ){ const [books, setBooks] = useState ([]); return ( <TransitionGroup component ="ul" > {books.map({id, name, author, date} => { return ( <CSSTransition key ={id} timeout ={500} classNames ="book" > <li > {name}-{author}-{date}</li > </CSSTransition > ) })} </TransitionGroup > ) }
CSSInJs 模板字符串的高级用法
标签函数第一个参数包含一个字符串数组, 其余的参数与表达式相关
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 const person = "Mike" ;const age = 28 ;function myTag (strings, personExp, ageExp ) { const str0 = strings[0 ]; const str1 = strings[1 ]; const str2 = strings[2 ]; const ageStr = ageExp > 99 ? "centenarian" : "youngster" ; return `${str0} ${personExp} ${str1} ${ageStr} ${str2} ` ; } const output = myTag`That ${person} is a ${age} .` ;console .log (output);fn`some string here` ; fn (['some string here' ]);const aVar = 'good' ;fn`this is a ${aVar} day` ; fn (['this is a ' , 'day' ], aVar);
影响打包性能, 导致 js 文件体积变大
动态生成唯一的 className, 对样式覆写不太友好
1 import styled from 'styled-components' ;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 const Title = styled.h1 ` font-size: 1.5em; text-align: center; color: #bf4f74; ` ;const Wrapper = styled.section ` padding: 4em; background: yellowlight; ` ;function App ( ){ return ( <Wrapper > <Title > title</Title > </Wrapper > ) } <section> <h1 > title</h1 > </section>
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 const Button = styled.button ` color: #bf4f74; font-size: 1em; margin: 1em; padding: 0.25em 1em; border: 2px solid #bf4f74; border-radius: 3px; ` ;const TomatoButton = styled (Button )` color: tomato; border-color: tomato; ` ;function App ( ){ return ( <> <Button > Normal Button</Button > <TomatoButton > Tomato Button</TomatoButton > </> ) } <button>Normal Button </button> <button > Tomato Button</button >
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 const Link = ({className, children} ) => ( <a className ={className} > {children} </a > ); const StyledLink = styled (Link )` color: #bf4f74; font-weight: bold; ` ;function App ( ){ return ( <> <Link > UnStyled Link</Link > <StyledLink > Styled Link</StyledLink > </> ) }
as 更改渲染结果 as props 更改样式化组件呈现的标签或组件
1 2 3 4 5 6 7 8 9 10 11 12 13 function App ( ){ return ( <> <Button > Normal Button</Button > <Button as ="a" href ="#" > Link with Button styles</Button > <TomatoButton as ="a" href ="#" > Link with Tomato Button styles</TomatoButton > </> ) } <button>Normal Button </button> <a href ="#" > Link with Button styles</a > <a href ="#" > Link with Tomato Button styles</a >
1 2 3 4 5 6 7 8 9 10 11 12 const ReverseButton = props => <Button { ...props } children ={ props.children.split ('').reverse () } /> function App ( ){ return ( <Button > Normal Button</Button > <Button as ={ ReverseButton }> Custom Button with Normal Button styles</Button > ) } <button>Normal Button </button> <button > selyts nottuB lamroN htiw nottuB motsuC</button >
获取 props 添加 $ 前缀将 props 转换为短暂的 props, 防止样式化组件使用的 props 被传入到底层的 React 组件或者 DOM 元素上
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 const Button = styled.button <{ $primary?: boolean }>` background: ${props => props.$primary ? '#bf4f74' : 'white' } ; color: ${props => props.$primary ? 'white' : '#bf4f74' } ; font-size: 1em; margin: 1em; padding: 0.25em 1em; border: 2px solid #bf4f74; border-radius: 3px; ` ;function App ( ){ return ( <> <Button > Normal Button</Button > <Button $primary > Primary Button</Button > </> ) } <button>Normal </button> <button > Primary</button >
attrs 属性重写 attrs 修改样式化组件的属性, 如果想防止样式化组件使用的 props 被传入到底层 React 组件或者 DOM 元素上, 使用 $ 前缀修饰 props 将其转换为短暂的 props
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 styled.tagName .attrs ({} | Function ); const Input = styled.input .attrs <{ $size?: string }>(props => ({ type : "text" , $size : props.$size || '1em' }))` border: 2px solid #BF4F74; /* use the dynamically computed prop */ margin: ${props => props.$size} ; padding: ${props => props.$size} ; ` ;const PassWordInput = styled (Input ).attrs ({type : 'password' })` border: 2px solid aqua; ` ;function App ( ){ return ( <> <Input placeholder ="A bigger text input" $size ="2em" /> <PassWordInput placeholder ="A normal password input" /> </> ) } <input type ="text" placeholder="A bigger text input" /> <input type ="password" placeholder ="A normal password input" />
其他组件和API
StyleSheetManager 管理样式化组件的辅助组件
ThemeProvider
ThemeConsumer
withTheme 高阶组件, 传递的组件将接收到一个包含 theme prop 的 theme 对象
1 2 3 4 5 6 7 8 import {withTheme} from 'styled-components' ;function App (props ){ return ( <button style ={{color: props.theme.color }}> Button</button > ) } export default withTheme (App );
useTheme 获取 ThemeProvider 传递的 theme 的 Hook
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 import {ThemeProvider , ThemeConsumer , useTheme} from 'styled-components' ;function App ( ){ return ( <ThemeProvider theme ={{color: 'mediumseagreen '}}> <Button /> </ThemeProvider > ) } function Button ( ){ const theme = useTheme (); const style = {color : theme.color }; return ( <button style ={style} > Button </button > ) } function Button ( ){ return ( <ThemeConsumer > {theme => <button style ={{color: theme.coloer }}> Button</button > } </ThemeConsumer > ) }
isStyledComponent 判断是否是样式化组件
createGlobalStyle 创建全局样式
css 创建样式片段
keyframes 创建动画的辅助函数
1 2 3 4 5 6 7 8 9 10 11 12 import {keyframes} from 'styled-components' ;const fadeIn = keyframes` 0% { opacity:0 } 100% { opacity: 1; } ` ;const FadeInButton = styled.button ` animation: 1s ${fadeIn} ease-out; ` ;
tailwindCSS tailwindcss
@tailwindcss/postcss
postcss
v3 版本支持 tailwind.config.js 配置文件
应用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 <div class ="3xl:text-lg text-gray-900 bg-white font-display rounded-sm bg-[#1da1f2]" > demo</div > <div class ="bg-[#316ff6] lg:top-[117px]" > 使用任意值</div > <div class ="grid grid-cols-[24rem_2.5rem_minmax(0, 1fr)]" > 使用任意值</div > <div class ="max-h-[calc(100vh - (--spacing(6)))]" > 使用任意值</div > <div class ="[mask-type:luminance] hover:[mask-type:alpha]" > css 属性</div > <div class ="bg-red-500!" > 样式优先级</div >
指令
@tailwind 插入样式到 base, components, utilities, variants, v4 不再支持该指令
base 用于重置规则或应用于html元素的默认样式
components 基于类的样式, 能够使用实用程序覆盖这些样式
utilities 实用程序用于小型、单一用途的类, 这些类应始终优先于任何其他样式
@import CSS 指令, 导入 tailwindcss
@theme 添加自定义主题变量或重置默认主题
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 @import 'tailwindcss' prefix(tw);@import 'tailwindcss' important;@theme { --color-dblue-300 : #0088ff ; --spacing-50 : '50rem' ; --tab-size-github : 8 ; }
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 39 40 41 42 43 @import 'tailwindcss' ;@layer base { h1 { font-size : var (--text-2 xl); } } @layer components { .card { background-color : var (--color-white); border-radius : var (--rounded-lg); padding : var (--spacing-6 ); box-shadow : var (--shadow-xl); @apply rounded-2 xl; } } @utility content-auto { content-visibility : auto; &::-webkit-scrollbar { display : none; } } @utility tab-* { tab-size : --value (integer); } .select2-dropdown { @apply rounded-b-lg shadow-md; } .my-element { background : white; @variant dark { background : black; } }
1 2 3 4 5 6 7 8 9 <div class ="card" > use @layer components difine classes</div > <div class ="content-auto hover:content-auto" > Hello World!</div > <div class ="tab-2 tab-4" > Function utility</div >
@reference 直接在 css 模块, style 标签内, 其他组件内使用 @apply, @variant, 自定义的主题中定义的样式避免重复的 css 输出
1 2 3 4 5 6 7 8 9 10 <style > @reference '../../app.css' ; @reference 'tailwindcss' ; h1 { @apply text-2 xl font-bold text-red-500 ; } </style >
@config 加载旧版本的 js 配置文件, v4 兼容旧版本
@plugin 加载旧版本的 js 配置文件中的插件, v4 兼容旧版本
函数
--alpha() 调整颜色的透明度
--spacing() 生成主题的间距值
1 2 3 4 5 .my-element { color : --alpha (var (--color-lime-300 ) / 50% ); margin : --spacing (4 ); margin : calc (var (--spacing) * 4 ); }
theme() 在编译时允许使用 tailwind 配置的值, 函数在构建时执行, v4 兼容旧版本
screen() 使用 tailwind 配置的值创建媒体查询
1 2 3 .my-element { margin : theme (spacing.12 ); }
classnames