React Router动画实践
写样式的方法
CSS Modules
需要注意的是需要创建一个scss的文件 里面用来写css 然后可以直接调用里面的样式(会帮你在样式名后面生成随机数以确保不重名)
1.选择器的复用 (完全等价)
2.当我们需要一个对象是有很多个类名 可以利用数组后面加上join
Style Components
优点:可以不用写CSS文件 也不用自己想类名 因为类名已经被赋值为随机数
unocss
表驱动编程
数据结构是静态的算法
例如可以利用类似于列表 对象中key value一一对应
让其能够在地址不同的时候 跳转到另一个地址栏
优化动画的细节
为了让用户能够打开页面的时候图片不闪烁
可以设置图片的宽高 这样可以避免图片加载慢带来的图片闪烁
对于初步的welcomelayout这个框架
import { animated, useTransition } from '@react-spring/web'
import { ReactNode, useState } from 'react'
import { useRef } from 'react'
import { Link, useLocation, useOutlet } from 'react-router-dom'
import logo from '../assets/images/logo.svg'
const linkMap = {//利用到的是表驱动编程 可以有这种一一对应的关系将不同path下对应的pages联系起来
'/welcome/1': '/welcome/2',
'/welcome/2': '/welcome/3',
'/welcome/3': '/welcome/4',
'/welcome/4': '/welcome/xxx',
}
export const WelcomeLayout: React.FC = () => {
const [extraStyle, setExtraStyle] = useState({position:'relative'})//利用usestate 将extraStyle中初始化postition:'ralative 便于后面让子元素在执行动画的过程中变化style
const map = useRef<Record<string, ReactNode>>({})
const location = useLocation()//得到当前地址栏的地址
const outlet = useOutlet()//useOutlet可以拿到<OutLet/>占位容器内所存放的组件对象
console.log("outlet:" )
console.log(outlet)
map.current[location.pathname] = outlet//将outlet中存放的组件对象一一赋值给map中的对应的不同的loaction.path
const transitions = useTransition(location.pathname, {
from: { transform: location.pathname === '/welcome/1' ? 'translateX(0%)' : 'translateX(100%)' },
enter: { transform: 'translateX(0%)' },
leave: { transform: 'translateX(-100%)' },
config: { duration: 300 },
onStart: () => {//开始执行时动画时操作
setExtraStyle({ position: 'absolute'})
},
onRest: () => {//结束执行动画时操作
setExtraStyle({ position: 'relative'})
}
})
//h-screen意思是高度与屏幕一样 主语需要的flex布局
//justify-center items-center可以直接让flex布局中的元素纵向横向居中
//grow-1是指的所在的那个元素会在没有兄弟元素占满父元素的前提下 自己优先去沾满
//而item-stretch则是自己的子元素会自动撑满自己
return (
<div className= 'bg-#5f34bf' h-screen flex flex-col items-stretch pb-16px>
<header shrink-0 text-center pt-64px>
<img src={logo} />
<h1>山竹记账</h1>
</header>
<main shrink-1 grow-1 m-16px relative>
{transitions((style, pathname) =>
<animated.div key={pathname} style={{...style, ...extraStyle}} flex w="100%" h="100% " p-16px>
<div bg-white flex justify-center items-center rounded-8px grow-1>
{map.current[pathname]}
</div>
</animated.div>
)}
</main>
<footer text-24px text-white text-center grid grid-cols-3 grid-rows-1 shrink-0>
<Link style={{ gridArea: '1 / 2 / 2 / 3 '}} to={linkMap[location.pathname]}>下一页</Link>
<Link style={{ gridArea: ' 1 / 3 / 2 / 4 '}} to="/welcome/xxx">跳过</Link>
</footer>
</div>
)
}