react-transition-group реализует эффект переключения маршрутизации

React.js

основное введение

Демонстрация эффекта

  • Краткое введение: я реализовал список часто задаваемых вопросов. Щелкните элемент списка, чтобы перейти на страницу сведений. Цель состоит в том, чтобы добавить эффекты перехода при переключении страниц, чтобы улучшить взаимодействие с пользователем.
  • Без эффекта перехода очень резкий переход на страницу сведений:
    无过渡效果演示
  • С добавленным эффектом перехода это выглядит лучше:
    过渡效果演示
  • Давайте посмотрим, как это реализовать.

основы реакции-перехода-группы

Официальная документация 👉документация группы реакции-перехода

  • В реактивном проекте библиотека анимационных переходов react-transition-group, предоставленная на официальном сайте, может использоваться для реализации эффекта перехода при переключении страниц (переключение маршрутизации).

  • В группе реакции-перехода выставлены три компонента, а именно:

    • Transition
    • CSSTransition
    • TransitionGroup
  • Наиболее важными из них являютсяCSSTransition,а такжеTransitionGroupАнимация перехода для элементов списка. Я также использую эти два компонента в проекте.

  • TransitionGroupНе предоставляет никакой анимации, конкретная анимация зависит от нашего пакетаTransition || CSSTransitionанимация, поэтому мы можем создавать различные типы анимации в списке.

  • CSSTransitionНаиболее важными API в компоненте являются:

    • in: логическое значение, отображение и скрытие компонента управления,trueпоказывать,falseСпрятать.

    • timeout: число, задержка, относится к продолжительности состояния анимации. Вы также можете передать объект, например{ exit:300, enter:500 }установить задержку на вход и на выход отдельно.

    • classNames: строка, имена классов, добавленные к элементу во время анимации. Обычно используйте это свойство для разработки анимации. Обратите внимание, что это classNames вместо className.

    • unmountOnExit: логическое значение, дляtrueКогда компонент удалит элемент в скрытом состоянии,falseКогда компонент сохраняет состояние в конце анимации без удаления элемента. обычно устанавливается наtrue.

    • появляются: логическое значение, дляfalseкогдаCSSTransitionПосле загрузки элемента управления анимация не выполняется, т.е.trueКогда элемент управления загружается, анимация выполняется немедленно. Если вы хотите, чтобы компонент имел анимацию для первого рендеринга, вам нужно установить его вtrue.

    • ключ: строка, это свойство должно соответствоватьTransitionGroupКомпонент используется, и ключ можно использовать для определения необходимости запуска анимации. Это свойство очень важно!

  • Роль атрибута classNames заключается в следующем: когда компонент анимируется, различные состояния анимации (ввод, выход, выполнение) будут объединены в новое имя класса в качестве суффикса атрибута className, напримерCSSTransitionКомпонент задает следующие свойства:

        <CSSTransition
          classNames={'fade'}
          appear={true}
          key={location.pathname}
          timeout={300}
          unmountOnExit={true}
        >
          /* 省略... */
        </CSSTransition>
  • будет генерироватьfade-enter,fade-enter-active,fade-enter-done,fade-exit,fade-exite-active,fade-exit-done,fade-appearтак же какfade-appear-activeНесколько имен классов. Каждое отдельное className соответствует отдельному состоянию.

Холодное знание React-маршрутизатора

  • Базовые знания о react-router можно найти в официальной документации 👉документация по реактивному маршрутизатору, и здесь повторяться не будем.

  • Вот то, что вы обычно не замечаетеSwitchХолодное знание компонентов также является ключом к реализации анимации переключения маршрутизации!

  • SwitchЕсть очень важное свойство: местоположение. Как правило, мы не устанавливаем свойство местоположения для этого компонента. Нет никакой разницы между этим атрибутом:

    • Не устанавливайте свойство местоположения:SwitchПодкомпоненты компонента (обычно Route или Redirect) будут сопоставлять маршрут в соответствии с местоположением текущего браузера в качестве основы для сопоставления.
    • Установите свойство местоположения:SwitchПодкомпоненты компонента будут сопоставляться с определенным местоположением.
  • Прочитав основное введение, давайте посмотрим, как использовать группу react-transition-group в проекте для достижения эффекта перехода при переключении страниц.

Завершить процесс

  • Прежде всего, согласно предыдущему блогу представил 👉Процесс настройки проекта react + typescriptПосле того, как проект построен, группа реагирования может быть введена в проект перед разработкой компонента. В то же время, поскольку я тоже использую в проекте typescript, мне также нужно установить @types/react-transition-group. Команда установки выглядит следующим образом:
yarn add react-transition-group
yarn add @types/react-transition-group --dev
  • В файле ввода App.tsx используйте:
import { createHashHistory } from 'history';
import React from 'react';
import { Router } from 'react-router';
import { Route, Switch, withRouter } from 'react-router-dom';
import { TransitionGroup, CSSTransition } from 'react-transition-group';
import routeData from './common/route'; // 路由配置
import NotFound from './views/Exception';

const history = createHashHistory();

const Routes = withRouter(({ location }) => (
  <TransitionGroup className={'router-wrapper'}>
    <CSSTransition timeout={300} classNames={'fade'} key={location.pathname} unmountOnExit={true}>
      <Switch>
        {routeData.map(({ path, component, exact }: IRouterItem) => (
          <Route key={path} path={path} component={component} exact={exact} />
        ))}
        <Route component={NotFound} />
      </Switch>
    </CSSTransition>
  </TransitionGroup>
));

const App: React.FC = () => {
  return (
    <Router history={history}>
      <Routes />
    </Router>
  );
};

export default App;
  • Роль withRouter: вы можете обернуть любой пользовательский компонент, и вы можете передать историю, местоположение и методы сопоставления react-router в объект реквизита в компонентах, которые не переключаются маршрутизацией.

По умолчанию this.props должен присутствовать в компоненте, который был обработан путем сопоставления маршрутов, чтобы иметь параметры маршрутизации и использовать программную навигацию. Однако не все компоненты напрямую подключены к маршрутизации (переход к этому компоненту через маршрутизацию).Когда этим компонентам нужны параметры маршрутизации, можно использовать withRouter для передачи параметров маршрутизации этому компоненту, а в это время можно использовать this.props.

  • Например, компонент App.js обычно является домашней страницей, он не перескакивает через роутинг, а открывается напрямую вводом адреса в браузере, если withRouter не используется, this.props этого компонента пуст, а реквизит не может быть выполнен, история, местоположение и методы сопоставления.

  • Чтобы сделать входной файл App.tsx более кратким, я инкапсулировал код, связанный с коммутацией маршрутизации, с помощью react-transition-group вRoutesкомпоненты.

  • Содержимое модифицированного входного файла App.tsx выглядит следующим образом:

import { createHashHistory } from 'history';
import React from 'react';
import { Router } from 'react-router';
import Routes from './components/Routes';

const history = createHashHistory();

const App: React.FC = () => {
  return (
    <Router history={history}>
      <Routes />
    </Router>
  );
};

export default App;
  • RoutesКомпоненты следующие:
import React from 'react';
import { Route, Switch, withRouter } from 'react-router-dom';
import { TransitionGroup, CSSTransition } from 'react-transition-group';
import routeData from '../../common/route';
import NotFound from '../../views/Exception';

interface IRouterItem {
  component?: React.ComponentType;
  path?: string;
  exact?: boolean;
}

class Routes extends React.Component<any> {
  render () {
    const { location } = this.props;
    return (
      <TransitionGroup className={'router-wrapper'}>
        <CSSTransition
          classNames={'fade'}
          appear={true}
          key={location.pathname}
          timeout={300}
          unmountOnExit={true}
        >
          <Switch location={location}>
            {routeData.map(({ path, component, exact }: IRouterItem) => (
              <Route key={path} path={path} component={component} exact={exact} />
            ))}
            <Route component={NotFound} />
          </Switch>
        </CSSTransition>
      </TransitionGroup>
    );
  }
}

export default withRouter(Routes);
  • Ключевым шагом в принятии решения о том, использовать ли анимационный эффект, является завершение соответствующего стиля анимации! Поскольку эффект анимации является глобальным, он должен быть написан в глобальном стиле.
  • Чтобы узнать больше о модульном меньшем и глобальном меньшем количестве, обратитесь к предыдущему блогу за подробностями 👉Процесс настройки проекта react + typescriptчтобы понять.
  • Мы должны сделать, это создать новый файл index.less в каталоге SRC следующим образом:
/* 动画相关样式 */
.fade-enter, .fade-appear {
  opacity: 0;
}

.fade-enter.fade-enter-active, .fade-appear.fade-appear-active {
  opacity: 1;
  transition: opacity 300ms ease-in;
}

.fade-exit {
  opacity: 1;
}

.fade-exit.fade-exit-active {
  opacity: 0;
}
  • Затем импортируйте его в файл ввода index.tsx:
import './index.less';
  • Выше можно добиться эффекта перехода страницы при переключении роутов, и багов нет (нет анимации при первой загрузке, и два запроса интерфейса).

⚠️Если вы просто хотите добиться эффекта перехода, вы можете добиться его по содержанию, описанному выше

⚠ ️Если вы хотите узнать причины двух вышеуказанных ошибок, вы можете продолжить читать следующий контент.

Ступая на яму

  • Нельзя сказать, что вы не наступили на яму, и код в начале не такой. Объясним, почему багов два: отсутствие анимации при первой загрузке и два запроса интерфейса.

Нет анимации при первой загрузке

  • Как упоминалось в статье, которую я написал ранее, я использую проект под названиемreact-loadableСторонняя библиотека используется для разделения кода, а компоненты загружаются по запросу. (Подробности см. в предыдущем блоге 👉Процесс настройки проекта react + typescriptчтобы понять)
  • Однако оказалось, что при использованииreact-loadableПосле первой загрузки нет эффекта перехода для переключения страниц, смотрите следующие эффекты:
    首次加载无动画
  • Видно, что при обновлении страницы страница со списком (первая страница) не имеет эффекта перехода, а при переходе на страницу сведений переход не происходит, что очень резко. ), затем перейдите на страницу сведений и вырежьте. Существуют эффекты перехода, и это проблема, с которой я столкнулся без эффектов перехода при первом переключении страниц.
  • Так как реализованная на этот раз функция относительно проста, то для решения этой проблемы можно лишь временно отказаться от нее в проекте.react-loadableДелайте компоненты загружаемыми по требованию 😭.
  • Содержимое измененного файла конфигурации маршрутизации route.tsx примерно следующее:
// path:src/common/route.tsx
import * as React from 'react';
import DetailPage from '../views/DetailPage';
import Exception from '../views/Exception';
import HomePage from '../views/HomePage';

const routeConfig: any = [
  {
    path: '/',
    component: HomePage,
  },
  {
    path: '/detail/:id',
    component: DetailPage,
  },
  /**
   * Exception 页面
   */
  {
    path: '/exception/404',
    component: Exception,
  },
];

function generateRouteConfig (route: IRouteConfig[]) {
  return route.map(item => {
    return {
      key: item.path,
      exact: typeof item.exact === 'undefined' ? true : item.exact,
      ...item,
      component: item.component,
    };
  });
}

export default generateRouteConfig(routeConfig);
  • Что касается причины такой ошибки в сочетании двух, она все еще находится под наблюдением.Если кто-то знает об этом, вы можете оставить сообщение, чтобы сообщить, или обновить его позже, когда вы узнаете причину.

запрос интерфейса дважды

  • Мы все знаем, что это обычно происходит в жизненном цикле реакции.componentDidMountВызов интерфейса в методе (запрос связанных данных).componentDidMountМетод будет выполняться сразу после render() и использоваться после извлечения данных.setState()Метод запускает повторный рендеринг.
  • В начале код, связанный с коммутацией маршрутизации, был инкапсулирован.RoutesКомпоненты следующие:
import React from 'react';
import { Route, Switch, withRouter } from 'react-router-dom';
import { TransitionGroup, CSSTransition } from 'react-transition-group';
import routeData from '../../common/route';
import NotFound from '../../views/Exception';

interface IRouterItem {
  component?: React.ComponentType;
  path?: string;
  exact?: boolean;
}

class Routes extends React.Component<any> {
  render () {
    const { location } = this.props;
    return (
      <TransitionGroup className={'router-wrapper'}>
        <CSSTransition
          classNames={'fade'}
          appear={true}
          key={location.pathname}
          timeout={300}
          unmountOnExit={true}
        >
          <Switch>
            {routeData.map(({ path, component, exact }: IRouterItem) => (
              <Route key={path} path={path} component={component} exact={exact} />
            ))}
            <Route component={NotFound} />
          </Switch>
        </CSSTransition>
      </TransitionGroup>
    );
  }
}

export default withRouter(Routes);
  • Отличие от безглючного кода в том, что его раньше не давали.SwitchКомпонент устанавливает свойство местоположения. В результате страница сведений открывается после первой загрузки, а интерфейс будет запрашиваться дважды при его вырезании.Подробности см. в следующей демонстрации:

接口请求两次演示

  • Почему? Упомянутый ранее:

SwitchЕсть очень важное свойство: местоположение. Как правило, мы не устанавливаем свойство местоположения для этого компонента. Нет никакой разницы между этим атрибутом:

  • Не устанавливайте свойство местоположения:SwitchПодкомпоненты компонента (обычно Route или Redirect) будут сопоставлять маршрут в соответствии с местоположением текущего браузера в качестве основы для сопоставления.
  • Установите свойство местоположения:SwitchПодкомпоненты компонента будут сопоставляться с определенным местоположением.
  • Скриншот блока кода ключа:
    代码
  • Объедините код 👆, чтобы увидеть объяснение👇:
    • CSSTransitionКлючевым свойством в этом компоненте является совпадениеTransitionGroupИспользуемый компонентом, вы можете использовать ключ, чтобы определить, нужно ли запускать анимацию.
    • При переключении маршрутов старое содержимое маршрута исчезнет через определенный период времени, а новое содержимое маршрута будет отображаться при переходе.В течение переходного периода одновременно будут существовать два узла, старый узел будет отображать старую маршрутизацию. контент, и новый узел будет отображать новый контент маршрутизации.
    • CSSTransitionКлючевое свойство в компоненте определяет, отображается ли узел, иRouterСвойство местоположения в компоненте будет обновляться при изменении маршрута, в качестве имени можно использовать только путь к местоположению.CSSTransitionКлючевое свойство в компоненте. При переключении маршрута объект местоположения изменится, а новый ключевой ключ вызовет появление двух страниц при повторном отображении страницы.CSSTransition.
    • если только датьCSSTransitionКогда компонент настраивает ключевой атрибут, будет обнаружено, что старый узел будет соответствовать новому содержимому маршрутизации, потому чтоRouteПо умолчанию компонент соответствует местоположению текущего браузера, чтобы старый узел соответствовал старому местоположению, вам нужно установитьSwitchСвойство местоположения компонента.
  • Повторный рендеринг компонентов приведет к повторным запросам на интерфейс, так что давайте быстроSwitchДобавьте атрибут местоположения к компоненту.
  • Содержание этой статьи представлено здесь, добро пожаловать, чтобы оставить сообщение, если вам это нравится, пожалуйста, поставьте лайк 👍, спасибо ❤️.