问题描述
我正在尝试使用preact-router
进行页面转换,我已经尝试将preact-transition-group
软件包与preact-css-transition-group
软件包一起使用,这给了我一个错误,无论如何这是我的基本设置:
import { h,FunctionComponent } from 'preact';
import Router from 'preact-router';
const App: FunctionComponent = () => {
return (
<Router>
<div path="/1" style="padding: 50px">
page 1 <a href="/2">page 2</a>
</div>
<div path="/2" style="padding: 50px">
page 2 <a href="/1">page 1</a>
</div>
</Router>
);
};
最好使用打字稿和/或preact-router
解决方案,但这不是必需的。
解决方法
请注意:这种方法可能不适用于嵌套路由。
使用这种方法时,您需要使用一个类来将每条路由包装在div中,该类将为该路由设置动画,并将key和path属性设置为该路由的路径,例如:
function wrapRoute(route: h.JSX.Element): h.JSX.Element {
return ( // the in class is the animation and the page class is makes sure that the old and new routes overlap
<div path={route.props.path} class="in page" key={route.props.path}>
{route}
</div>
);
}
然后您需要添加两个反应变量,如下所示:
const [previousEl,setPreviousEl] = useState<ComponentChildren | null>(null);
const [outEl,setOutEl] = useState<JSX.Element | null>(null);
之后,您可以监听onChange
的{{1}}事件,并将preact-router
设置为div,该div包裹outEl
并具有将退出动画的类路径,然后添加一个previousEl
侦听器,以便您可以将onAnimationEnd
设置为outEl
,直到动画结束,最后需要将null
设置为previousEl
,您的路由器组件侦听器应如下所示:
e.current.props.children
最后要做的就是创建动画,请看下面的<Router onChange={(e) => {
if (previousEl) {
setOutEl(
<div class="out page" key={e.previous} onAnimationEnd={() => setOutEl(null)}>
{previousEl}
</div>
);
}
if (e.current) {
setPreviousEl(e.current.props.children);
}
}}
>
{routes} // this is an array containing all the wrapped routes.
</Router>
示例。
这是完整的示例:
app.tsx
app.sass
app.sass
import { h,FunctionComponent,JSX,ComponentChildren,Fragment } from 'preact';
import Router from 'preact-router';
import { useState } from 'preact/hooks';
import './app.sass'
const routes = [
<div style="padding: 50px; background: red" path="/1">
page 1 <a href="/2">page 2</a> <a href="/3">page 3</a>
</div>,<div style="padding: 50px; background: blue" path="/2">
page 2 <a href="/1">page 1</a> <a href="/3">page 3</a>
</div>,<div style="padding: 50px; background: green" path="/3">
page 2 <a href="/1">page 1</a> <a href="/2">page 2</a>
</div>,].map((route) => wrapRoute(route));
function wrapRoute(route: h.JSX.Element): h.JSX.Element {
return (
<div path={route.props.path} class="in page" key={route.props.path}>
{route}
</div>
);
}
const App: FunctionComponent = () => {
const [previousEl,setPreviousEl] = useState<ComponentChildren | null>(null);
const [outEl,setOutEl] = useState<JSX.Element | null>(null);
return (
<Fragment>
<Router
onChange={(e) => {
if (previousEl) {
setOutEl(
<div class="out page" key={e.previous} onAnimationEnd={() => setOutEl(null)}>
{previousEl}
</div>
);
}
if (e.current) {
setPreviousEl(e.current.props.children);
}
}}
>
{routes}
</Router>
{outEl}
</Fragment>
);
};
export default App;
,
创建动画的最佳方法是引入另一个HOC-高阶组件,该组件包装您的页面并将其用作路由器目标。就像这样:
import { h,FunctionComponent } from 'preact';
import Router from 'preact-router';
const App: FunctionComponent = () => {
return (
<Router>
<PageAnimation path="/1">
<div style="padding: 50px">
page 1 <a href="/2">page 2</a>
</div>
</PageAnimation>
<PageAnimation path="/2">
<div style="padding: 50px">
page 2 <a href="/1">page 1</a>
</div>
</PageAnimation>
</Router>
);
};
您的实现代码将类似于- How to make transition animation。