javascript - როგორ შემიძლია გვერდის გადასვლის შექმნა preact-თან ერთად


მე ვცდილობ გვერდის გადასვლის მიღებას 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 გადაწყვეტა, მაგრამ აუცილებელი არაა.

პასუხი #1

შენიშვნა: ეს მიდგომა ალბათ არ მუშაობს გატოლებული მიმართულებებით.

ამ მიდგომით, თქვენ უნდა გაახვიოთ ყოველივე მარშრუტი 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 ღონისძიება preact-router-ისგან და დააყენოთ outEl div-ზე, რომელიც იხვევს 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.sass მაგალითი.

აქ არის სრული მაგალითი:

app.tsx

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;

აპლიკაცია.sass

.page
  position: absolute
  top: 0
  bottom: 0
  left: 0
  right: 0

.out
  animation: out 200ms forwards

@keyframes out
  0%
    opacity: 1
    transform: translateX(0)
  100%
    opacity: 0
    transform: translateX(100vw)

.in
  animation: in 200ms forwards

@keyframes in
  0%
    opacity: 0
    transform: translateX(-100vw)
  100%
    opacity: 1
    transform: translateX(0)

პასუხი #2

ყველაზე კარგი გზა ანიმაციის შექმნისთვის არის სხვა 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>
  );
};

თქვენი იმპლემენტაციის კოდი შეიძლება იყოს ასეთია - როგორ გააკეთოთ ტრანზიციის ანიმაცია.