前言
最近组内在使用react重构之前的老项目, 遇到个很典型的需求,异步加载页面和页面过场动画结合。 组内大佬找了一下, 没找到合适的方法,我就自己也试了一下。view url
实现思路
异步加载组件和代码切割使用的是官方提供的Suspense, lazy
实现比较简单
1 2
| const Hello = lazy(() => import("./views/hello")); const Home = lazy(() => import("./views/home"));
|
路由使用的是react-router-dom@5.1.2
动画使用的是react-transition-group
话不多说直接上代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| <Route render={({ location }) => ( <TransitionGroup> <CSSTransition key={location.pathname} classNames={forward ? "forward" : "back"} appear timeout={5000} > <Switch location={location}> {routes.map(r => { return ( <Route exact={r.exact} path={r.path} key={r.path}> {wrap(r.Component)} </Route> ); })} </Switch> </CSSTransition> </TransitionGroup> )} />
|
这里兼具了动态路由的实现, 没有完全使用官方文档的jsx配置思路,使用json对象配置比较灵活, 可以做一些类似根据权限动态生成, 根据打包参数动态打包路由等骚操作。
顺便实现了一个简易的eventBus, 有一次面试问到实现,这次重新组织了一下数据结构,bus使用二维数组实现, 更加扁平, 仅供参考.
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 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
| type EventBus = { bus: Array<string | Function>[]; emit: (evt: string, payload?: any) => void; on: (evt: string, listener: Function) => void; off: (evt: string, listener: Function) => void; };
const eventBus: EventBus = { bus: [], emit(evt: string, payload?: any) { const { bus } = eventBus; let i = 0; while (i < bus.length) { if (!bus[i]) { i++; continue; } const [name, ...listeners] = bus[i]; console.log(evt, name, listeners, i); if (name && listeners.length) { if (name === evt) { listeners.forEach(listener => { if (typeof listener === "function") { console.log("before call", listener); listener(payload); } }); } } i++; } }, on(evt: string, listener: Function) { const { bus } = eventBus; if (!bus.length) { bus.push([evt, listener]); return; } let i = 0; let has = false; while (i < bus.length) { i++; if (!bus[i]) continue; const [name, ...listeners] = bus[i]; if (name === evt) { if (listeners.indexOf(listener) <= 0) { has = true; bus[i].push(listener); } } } if (!has) { bus.push([evt, listener]); } }, off(evt: string, listener: Function) { const { bus } = eventBus; let i = 0; if (!bus.length) return;
while (i < bus.length) { i++; if (!bus[i]) continue; const [name, ...listeners] = bus[i]; if (evt === name) { const index = listeners.findIndex(l => l === listener); listeners.splice(index, 1); } } } };
|
写在最后
其实看似简单的需求和功能, 足足花费了我大半天, 说明自己对于react生态还是不熟悉, 所以特此记录下来。github