我如何创建带有预言的页面过渡

问题描述

我正在尝试使用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