React16.7 обновляет приложение Web Music

React.js

предисловие

В прошлом году я написал приложение для веб-музыки и опубликовал серию статей, чтобы представить процесс разработки.create-react-appПроекты, построенные официальными лесами,react-scriptsда1.xверсия, в то время как версия реакции16.2.0, в октябре прошлого годаcreate-react-appуже опубликовано2.0Версия,reactОбновлен до декабря прошлого года16.7.0

Итеративное обновление технологий в области переднего плана происходит слишком быстро, и люди часто жалуютсяпожалуйста, не обновляйте,я не могу учиться,я не могу закончить

Быть фронте, вы должны быть готовы учиться в любое время, в противном случае вы будете устранены ⊙﹏⊙∥| °

Пока вы занимаетесь разработкой, вы должны поддерживать активное обучение, будь то в области фронтенда или в области бэкенда, но интервал между изучением новых технологий во фронтенде больше, чем в бэкенде. задний конец. Как специалист по Java, я хорошо понимаю o(╯□╰)o

Введение обновления

create-react-app

И по сей день,create-react-appОн был обновлен до версии 2.x, в основном для обновления многих инструментов, от которых он зависит.Эти инструменты выпустили новые версии с новыми функциями и улучшениями производительности, такими какbabel7,webpack4,babel7а такжеwebpack4Каковы конкретные обновления, оптимизация, которые каждый может пойти, чтобы увидеть информацию. Дальшеcreate-react-appНекоторые обновленные точки

  • Добавлен препроцессор Sass, модульная поддержка CSS.
  • Обновление до Babel7
  • Обновление до веб-пакета4
  • новыйpreset-env

Чтобы узнать больше об обновлениях, нажмитездесь

react16.3

Поскольку раньше я использовал реакцию 16.2, когда дело доходит до реакции 16.7, мне приходится начинать с версии 16.3.

16.3 добавлено несколько новыхфункция жизненного цикла,context API,createRef APIа такжеforwardRef API, две новые функции жизненного циклаgetDerivedStateFromPropsа такжеgetSnapshotBeforeUpdateВ основном для замены предыдущегоcomponentWillMount, componentWillReceivePropsа такжеcomponentWillUpdate, цель состоит в том, чтобы поддержатьerror boundariesи предстоящийasync rendering mode(асинхронный рендеринг). когда используешьasync rendering modeКогда первоначальный рендеринг прерывается, прерванное поведение обработки ошибок может привести к утечкам памяти, и использованиеcomponentWillMount, componentWillReceivePropsа такжеcomponentWillUpdateувеличивает вероятность таких проблем

В предыдущей версии было два способа получить DOM или компонент: первый — дать ссылку, указать имя, а затем использовать refs.name или ReactDOM.findDOMNode(name), чтобы получить его, а второй — использовать ref callback, чтобы дать ref функцию обратного вызова. В начале я использовал первый, а потом перешел на коллбек ref, который сейчас официально объявлен устаревшим, рекомендуется использовать коллбек ref, так как у первого есть нескольконедостаток, использовать обратный вызов ref немного проблематично, поэтому предоставляется официальная новая операцияcreateRef API

Как получить dom при использовании функционального компонента,forwardRef APIПозволяет использовать функциональные компоненты и передавать ref в подкомпоненты, так что вы можете легко получить дом в подкомпоненте

Для получения дополнительной информации нажмитездесь

react16.6

Мне до сих пор очень нравится обновление этой версии, официальное наконец-то поддерживает то же, что и vueCode Splittingохватывать

Использование в реакцииCode Splitting, беда в том, чтобы самому написать компонент ленивой загрузки, или просто использовать стороннюю библиотеку. Теперь официально добавленоReact.lazyа такжеSuspenseиспользуется для поддержкиCode Splitting

import React, {lazy, Suspense} from 'react';
const LazyComponent = lazy(() => import('./LazyComponent'));

function MyComponent() {
  return (
    <Suspense fallback={<div>Loading...</div>}>
      <LazyComponent />
    </Suspense>
  );
}

Примечание. React.lazy и Suspense в настоящее время не поддерживают рендеринг на стороне сервера, а рендеринг на стороне сервера официально рекомендуется.Loadable Components

В компоненте класса есть функция жизненного циклаshouldComponentUpdateИспользуется, чтобы сообщить компоненту, следует ли отображать, наследоватьReact.component, вы можете сами пересоздать этот метод, чтобы судить и решать, как рендерить, наследоватьReact.PureComponent, который уже реализован по умолчаниюshouldComponentUpdate, он поверхностно сравнивает свойства и состояние и отображает только в том случае, если они не равны и не могут быть переписаны вами самостоятельно.shouldComponentUpdate. Для функциональных компонентов у него нет такой функции, новой в этой версииReact.memo, так что функциональная компонента имеет иReact.PureComponentта же функция

Добавлено в 16.3context API, при использовании контекста вам нужно использоватьConsumerкак ниже

const ThemeContext = React.createContext('light');
...

class MyComponent extends React.Component {
  render() {
    return (
      <ThemeContext.Consumer>
        {theme => /* 使用context */}
      </ThemeContext.Consumer>
    );
  }
}

Теперь вы можете использовать более удобныйstatic contextType

const ThemeContext = React.createContext('light');
...

class MyComponent extends React.Component {
  render() {
    let value = this.context;
    /* 使用context */
  }
}
MyComponent.contextType = ThemeContext;

Для получения дополнительной информации нажмитездесь

Обновить

Это обновление основано наисходный код

Перед запуском внесите некоторые изменения в каталог компонентов, используйте обычное имя каталога для хранения соответствующих компонентов, создайте новый каталог представлений, переместите компоненты из каталога компонентов в каталог представлений, а затем переместите компоненты из общего каталога в каталог компонентов

Изменить настройку

Начните обновление сейчас, будетreact-scriptsобновитесь до2.1.3,reactобновитесь до16.7.0

npm install --save --save-exact react-scripts@2.1.3
npm install react@16.7.0 react-dom@16.7.0

Подождите минутку

бегатьnpm run start

Было обнаружено, что было сообщено об ошибке, основанной наreact-scriptsВерсия 1.x настроила скрипт,react-scriptsКонфигурация сильно изменилась в версии 2.x, в результате чего оригинальный пользовательский скрипт использовать нельзя. Кроме того, поиск способа изменить конфигурацию занимает слишком много времени.Если вы знакомы с конфигурацией веб-пакета, запустите встроенныйejectИзвлеките файл конфигурации или найдите третью сторонуcustomize-cra,в этом случае нужно подробнее узнать о способе настройки.Если автор его не поддержит,реакт-скрипты сильно обновятся,и он не сможет вовремя адаптироваться к новой версии.Вот выбираю насилие и извлеките файл конфигурации.

let's do it

бегатьnpm run eject

scriptsКаталог уже есть в проекте (скрипт, написанный кастомной конфигурацией ранее), удалите его, запустите снова, подождите некоторое время и добавьте после выполнения множество зависимостей в package.json, а также немного postcss, babel и конфигурации eslint

wait

пакет.jsonscriptsСкрипт не обновлен, обратитесь к другимnpm run ejectПослеscripts, а затем измените его следующим образом

"scripts": {
  "start": "npm run dev",
  "dev": "node scripts/start.js",
  "build": "node scripts/build.js"
}

После извлечения появляются зависимости, связанные с разработкойdependencies, а затем поместите связанные с разработкой зависимости вdevDependenciesИ удалить зависимости, связанные с шуткой

бегатьnpm run dev

Подскажите, добавить ли конфигурацию списка браузеров, введите Y и нажмите Enter, тогда появится следующая ошибка, и стиль страницы нарушен

Module not found: Can't resolve '@/api/config'

В настоящее время псевдонимы не настроены@а такжеstylus

Откройте WebPack.config.js в каталоге config, чтобы найти конфигурацию.resolveпод узломalias, добавьте псевдоним

config/webpack.config.js

module.exports = function(webpackEnv) {
  ...
  
  return {
    ...
    resolve: {
      ...
      alias: {
        // Support React Native Web
        // https://www.smashingmagazine.com/2016/08/a-glimpse-into-the-future-with-react-native-for-web/
        'react-native': 'react-native-web',
        '@': path.join(__dirname, '..', "src")
      },
    }
  }
  ...
}

оalias,использоватьaliasОн может сократить время упаковки вебпака, но он не дружественен к IDE или инструментам, и его нельзя перепрыгнуть, очень неудобно просматривать код. Если выдержите, настройте, если не выдержите, напишите относительный путь при импорте, используйте его здесь.aliasДля демонстрации окончательный исходный код не используетсяalias

Тогда есть стилус.Официал поддерживает только sass.Может быть, что многие используют sass.Вы должны поддерживать еще несколько.≡(▔﹏▔)≡

Прежде чем использовать CSS в оригинальном виде, есть серьезная проблема, то есть будет проблема конфликтов CSS.Решений таких проблем много, напримерstyled-compoents,styled-jsxа такжеcss modules, первые два просто альтернативные,css modulesОн не подрывает оригинальный CSS, но также поддерживает CSS-процессоры, не зависит от фреймворка и может использоваться не только в React, но и в Vue. Чтобы включить модули css в веб-пакете, просто дайтеcss-loaderОдинmodulesВарианта достаточно.В проекте иногда css-файлы будут использовать css-модули, а некоторые нет.Для этого требованияresct-scriptsэто так хорошо подходит

config/webpack.config.js

...
// style files regexes
const cssRegex = /\.css$/;
const cssModuleRegex = /\.module\.css$/;
const sassRegex = /\.(scss|sass)$/;
const sassModuleRegex = /\.module\.(scss|sass)$/;

// This is the production and development configuration.
// It is focused on developer experience, fast rebuilds, and a minimal bundle.
module.exports = function(webpackEnv) {
  ...
  return {
    ...
    module: {
      strictExportPresence: true,
      rules: [
        ...,
        {
          test: cssRegex,
          exclude: cssModuleRegex,
          use: getStyleLoaders({
            importLoaders: 1,
            sourceMap: isEnvProduction && shouldUseSourceMap,
          }),
          sideEffects: true,
        },
        // Adds support for CSS Modules (https://github.com/css-modules/css-modules)
        // using the extension .module.css
        {
          test: cssModuleRegex,
          use: getStyleLoaders({
            importLoaders: 1,
            sourceMap: isEnvProduction && shouldUseSourceMap,
            modules: true,
            getLocalIdent: getCSSModuleLocalIdent,
          }),
        },
        // Opt-in support for SASS (using .scss or .sass extensions).
        // By default we support SASS Modules with the
        // extensions .module.scss or .module.sass
        {
          test: sassRegex,
          exclude: sassModuleRegex,
          use: getStyleLoaders(
            {
              importLoaders: 2,
              sourceMap: isEnvProduction && shouldUseSourceMap,
            },
            'sass-loader'
          ),
          sideEffects: true,
        },
        // Adds support for CSS Modules, but using SASS
        // using the extension .module.scss or .module.sass
        {
          test: sassModuleRegex,
          use: getStyleLoaders(
            {
              importLoaders: 2,
              sourceMap: isEnvProduction && shouldUseSourceMap,
              modules: true,
              getLocalIdent: getCSSModuleLocalIdent,
            },
            'sass-loader'
          ),
        },
        ...
      ]
    }
  }
}

В приведенной выше конфигурацииgetStyleLoadersЭто функция, которая возвращает конфигурацию загрузчика стилей и возвращает различные конфигурации в соответствии с переданными параметрами. В правилах начните с.cssили.(scss|sass)В конце используйте обычный загрузчик, с.moduels.cssили.module.(scss|sass)Включите css-модули в конце. Если вам нужно использовать модули css, добавьте .module перед суффиксом после имени файла.Соглашение об именовании файлов стилей в реакции совпадает с именем файла компонента, а компоненты и стили размещаются в одном каталоге.Если есть представляет собой файл с именем RecommendList.js , тогда файл стиля называется рекомендацией-список.модуль.css, и при объединении он становится следующим

Как может быть такой длинный хвост

Как убрать этот длинный хвост не влияя на использование css модулей, используем конфигурацию webpackRule.oneOfа такжеRule.resourceQuery

существуетwebpack.config.jsДобавьте конфигурацию стилуса в

config/webpack.config.js

...
// style files regexes
const cssRegex = /\.css$/;
const cssModuleRegex = /\.module\.css$/;
const sassRegex = /\.(scss|sass)$/;
const sassModuleRegex = /\.module\.(scss|sass)$/;
const stylusRegex = /\.(styl|stylus)$/;

// This is the production and development configuration.
// It is focused on developer experience, fast rebuilds, and a minimal bundle.
module.exports = function(webpackEnv) {
  ...
  return {
    ...
    module: {
      strictExportPresence: true,
      rules: [
        ...,
        // Adds support for CSS Modules, but using SASS
        // using the extension .module.scss or .module.sass
        {
          test: sassModuleRegex,
          use: getStyleLoaders(
            {
              importLoaders: 2,
              sourceMap: isEnvProduction && shouldUseSourceMap,
              modules: true,
              getLocalIdent: getCSSModuleLocalIdent,
            },
            'sass-loader'
          ),
        },
        {
          test: stylusRegex,
          oneOf: [
            {
              // Match *.styl?module
              resourceQuery: /module/,
              use: getStyleLoaders(
                {
                  camelCase: true,
                  importLoaders: 2,
                  sourceMap: isEnvProduction && shouldUseSourceMap,
                  modules: true,
                  getLocalIdent: getCSSModuleLocalIdent,
                },
                'stylus-loader'
              )
            },
            {
              use: getStyleLoaders(
                {
                  importLoaders: 2,
                  sourceMap: isEnvProduction && shouldUseSourceMap,
                },
                'stylus-loader'
              )
            }
          ]
        },
        ...
      ]
    }
  }
}

oneOfИспользуется для получения одного из первых правил сопоставления,resourceQueryсоответствоватьimport style from 'xxx.styl?module', поэтому вам нужно использовать модуль css и добавить его после?module, вам не нужно напрямуюimport 'xxx.styl',camelCase: trueЭто параметр конфигурации в css-loader, что означает включение горбового именования.Чтобы использовать css-модули, вам нужно получить имя скомпилированного стиля через атрибут объекта.Если имя стиля разделено тире, вам нужно использовать селектор атрибутов, такой как style['css-name '], после включения верблюжьего регистра имен вы можете style.cssName

На данный момент стиль страницы нормальный, но css модули не использовались, а потом все css нужно поменять на css модули, что является утомительным процессом, возьмем в качестве примера компонент Recommend

сначала импортировать стиль

import style from "./recommend.styl?module"

Затем получите стиль через объект стиля

class Recommend extends React.Component {
  ...
  render() {
    return (
      <div className="music-recommend">
        <Scroll refresh={this.state.refreshScroll}
          onScroll={(e) => {
            /* 检查懒加载组件是否出现在视图中,如果出现就加载组件 */
            forceCheck();
          }}>
          <div>
            <div className="slider-container">
              <div className="swiper-wrapper">
                {
                  this.state.sliderList.map(slider => {
                    return (
                      <div className="swiper-slide" key={slider.id}>
                        <div className="slider-nav" onClick={this.toLink(slider.linkUrl)}>
                          <img src={slider.picUrl} width="100%" height="100%" alt="推荐" />
                        </div>
                      </div>
                    );
                  })
                }
              </div>
              <div className="swiper-pagination"></div>
            </div>
            <div className={style.albumContainer} style={this.state.loading === true ? { display: "none" } : {}}>
              <h1 className={`${style.title} skin-recommend-title`}>最新专辑</h1>
              <div className={style.albumList}>
                {albums}
              </div>
            </div>
          </div>
        </Scroll>
        ...
      </div>
    );
  }
}

Некоторые из них являются фиксированными примерами имен плагинов, а некоторые являются фиксированными примерами имен, используемых для переключения скинов.Они не могут использовать модули css, поэтому вам необходимо использовать их в настоящее время.:global(), указывающий глобальные стили, css-loader не будет обрабатывать имена стилей, такие как

:global(.music-recommend)
  width: 100%
  height: 100%
  :global(.slider-container)
    height: 160px
    position: relative
    :global(.slider-nav)
      display: block
      width: 100%
      height: 100%
    :global(.swiper-pagination-bullet-active)
      background-color: #DDDDDD

Из-за добавления eslint появилось следующее предупреждение

./src/components/recommend/Recommend.js
  Line 131:  The href attribute is required for an anchor to be keyboard accessible. Provide a valid, navigable address as the href value. If you cannot provide an href, but still need the element to resemble a link, use a button and change it with appropriate styles. Learn more: https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/anchor-is-valid.md  jsx-a11y/anchor-is-valid
./src/components/singer/SingerList.js
  Line 153:  The href attribute is required for an anchor to be keyboard accessible. Provide a valid, navigable address as the href value. If you cannot provide an href, but still need the element to resemble a link, use a button and change it with appropriate styles. Learn more: https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/anchor-is-valid.md  jsx-a11y/anchor-is-valid
  Line 159:  The href attribute is required for an anchor to be keyboard accessible. Provide a valid, navigable address as the href value. If you cannot provide an href, but still need the element to resemble a link, use a button and change it with appropriate styles. Learn more: https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/anchor-is-valid.md  jsx-a11y/anchor-is-valid

Это правило предусматривает, что тег a должен указывать допустимый href, просто замените тег a чем-то другим.

ref

Я уже говорил, что добавил react16.3createRef API, затем замените обратный вызов ref этим новым API. Возьмем компонент Альбом в качестве примера.

существуетconstructorиспользуется вReact.createRef()инициализация

src/views/album/Album.js

class Album extends React.Component {
  constructor(props) {
    super(props);

    // React 16.3 or higher
    this.albumBgRef = React.createRef();
    this.albumContainerRef = React.createRef();
    this.albumFixedBgRef = React.createRef();
    this.playButtonWrapperRef = React.createRef();
    this.musicalNoteRef = React.createRef();
  }
  ...
}

Используйте ref, чтобы указать инициализированное значение

render() {
  ...
  return (
    <CSSTransition in={this.state.show} timeout={300} classNames="translate">
      <div className="music-album">
        <Header title={album.name}></Header>
        <div style={{ position: "relative" }}>
          <div ref={this.albumBgRef} className={style.albumImg} style={imgStyle}>
            <div className={style.filter}></div>
          </div>
          <div ref={this.albumFixedBgRef} className={style.albumImg + " " + style.fixed} style={imgStyle}>
            <div className={style.filter}></div>
          </div>
          <div className={style.playWrapper} ref={this.playButtonWrapperRef}>
            <div className={style.playButton} onClick={this.playAll}>
              <i className="icon-play"></i>
              <span>播放全部</span>
            </div>
          </div>
        </div>
        <div ref={this.albumContainerRef} className={style.albumContainer}>
          <div className={style.albumScroll} style={this.state.loading === true ? { display: "none" } : {}}>
            <Scroll refresh={this.state.refreshScroll} onScroll={this.scroll}>
              <div className={`${style.albumWrapper} skin-detail-wrapper`}>
                ...
              </div>
            </Scroll>
          </div>
          <Loading title="正在加载..." show={this.state.loading} />
        </div>
        <MusicalNote ref={this.musicalNoteRef}/>
      </div>
    </CSSTransition>
  );
}

пройти черезcurrentсвойство получает экземпляр dom или компонента,

scroll = ({ y }) => {
  let albumBgDOM = this.albumBgRef.current;
  let albumFixedBgDOM = this.albumFixedBgRef.current;
  let playButtonWrapperDOM = this.playButtonWrapperRef.current;
  if (y < 0) {
    if (Math.abs(y) + 55 > albumBgDOM.offsetHeight) {
      albumFixedBgDOM.style.display = "block";
    } else {
      albumFixedBgDOM.style.display = "none";
    }
  } else {
    let transform = `scale(${1 + y * 0.004}, ${1 + y * 0.004})`;
    albumBgDOM.style.webkitTransform = transform;
    albumBgDOM.style.transform = transform;
    playButtonWrapperDOM.style.marginTop = `${y}px`;
  }
}
selectSong(song) {
  return (e) => {
    this.props.setSongs([song]);
    this.props.changeCurrentSong(song);
    this.musicalNoteRef.current.startAnimation({
      x: e.nativeEvent.clientX,
      y: e.nativeEvent.clientY
    });
  };
}

Когда ref используется в теге html, current — это ссылка на элемент dom, а когда ref используется в компоненте, current — это экземпляр после монтирования компонента. После того, как компонент смонтирован, текущий будет указывать на элемент dom или экземпляр компонента, после выгрузки компоненту будет присвоено значение null, а ссылка будет обновлена ​​до обновления компонента.

Code Splitting

Разделение кода может уменьшить размер js-файлов, ускорить передачу файлов и загрузку по требованию.Теперь react официально предоставляетReact.lazyа такжеSuspenseЧтобы поддержать разделение кода, нажмите, чтобы узнать о них подробнее.здесь

Раньше маршруты прописывались прямо в компонентах, но теперь маршруты дизассемблированы, и маршруты единообразно настраиваются в конфигурационном файле, что удобно для централизованного управления

Добавьте каталог маршрутизатора в каталог src, а затем создайте новый.router.js

import React, { lazy, Suspense } from "react"

let RecommendComponent = lazy(() => import("../views/recommend/Recommend"));
const Recommend = (props) => {
  return (
    <Suspense fallback={null}>
      <RecommendComponent {...props} />
    </Suspense>
  )
}

let AlbumComponent = lazy(() => import("../containers/Album"));
const Album = (props) => {
  return (
    <Suspense fallback={null}>
      <AlbumComponent {...props} />
    </Suspense>
  )
}

...

const router = [
  {
    path: "/recommend",
    component: Recommend,
    routes: [
      {
        path: "/recommend/:id",
        component: Album
      }
    ]
  },
  ...
];

export default router

В использованииlazyНеобходимо использовать внешний слой компонента, обернутого методомSuspenseупаковать и указатьfallback,fallbackОтрисовывается при загрузке ресурса, соответствующего компоненту, здесь ничего не отрисовывается, укажитеnull. В официальном примере вRouteИспользуется только один внешний слойSuspense,посмотреть здесь, здесь будут подмаршруты, если они используются в самом внешнем слоеSuspense, Рендеринг дочернего элемента при отложенной загрузке резервного маршрута заменит содержимое компонентов представления родительского узла, что приведет к потере содержимого родительского компонента страницы, после завершения рендеринга представления маршрута подсборки появится все содержимое середине процесса перепрошивки, поэтому лучше всего в каждом компоненте представления маршрутизации сSuspenseпакет. тебе следуетpropsВручную передайте его компоненту ленивой загрузки, чтобы вы могли получить реактивный маршрутизаторmatch,historyЖдать

Использование апелляцииSuspenseВ части есть дублирующийся код, давайте трансформируем его компонентами высокого порядка

const withSuspense = (Component) => {
  return (props) => (
    <Suspense fallback={null}>
      <Component {...props} />
    </Suspense>
  );
}

const Recommend = withSuspense(lazy(() => import("../views/recommend/Recommend")));
const Album = withSuspense(lazy(() => import("../containers/Album")));

const router = [
  {
    path: "/recommend",
    component: Recommend,
    routes: [
      {
        path: "/recommend/:id",
        component: Album
      }
    ]
  },
  ...
];

Далее используйте эти конфигурации

Сначала поместите маршрут первого уровня, поместите его вAppкомпонент, нормальная работа такова<Route path="/recommend" component={Recommend} />, с помощьюreact-router-config, не нужно писать вручную, просто позвонитеrenderRoutesметод, вы можете передать в конфигурации маршрутизации

Примечание. Конфигурация маршрутизации должна использовать несколько фиксированных свойств, большинство иRouteКомпонентные реквизиты одинаковы

Установите react-router-config, где версия react-router ниже, а также используется более низкая версия react-router-config

npm install react-router-config@1.0.0-beta.4

src/views/App.js

import { renderRoutes } from "react-router-config"
import router from "../router"

class App extends React.Component {
  ...
  render() {
    return (
      <Router>
         ...
        <div className={style.musicView}>
          {/*
            Switch组件用来选择最近的一个路由,否则没有指定path的路由也会显示
            Redirect重定向到列表页
          */}
          <Switch>
            <Redirect from="/" to="/recommend" exact />
            {/* 渲染 Route */}
            { renderRoutes(router) }
          </Switch>
        </div>
      </Router>
    );
  }
}

RedirectОн используется для перенаправления и должен быть размещен вверху, иначе он не сработает.renderRoutesКомпонент Route будет создан в соответствии с конфигурацией, аналогичной<Route path="/recommend" component={Recommend} />

Затем используйте конфигурацию подмаршрута в компоненте «Рекомендовать».

src/views/recommend/Recommend.js

import { renderRoutes } from "react-router-config"

class Recommend extends React.Component {
  render() {
    let { route } = this.props;
    return (
      <div className="music-recommend">
        ...
        <Loading title="正在加载..." show={this.state.loading} />
        { renderRoutes(route.routes) }
      </div>
    );
  }
}

передачаrenderRoutesПосле этого конфигурация маршрутизации текущего уровня будет передана вroute, то черезroute.routesПолучите конфигурацию подмаршрутизации и т. д. для фейдеров и сабвуферов.

Исходный код renderRoutesпосмотреть здесь

Существуют и другие маршруты компонентов, которые необходимо изменить, и все они могут использоваться таким образом.

предварительный просмотр

Адрес предварительного просмотра:dxx.github.io/mango-music

QR код:

исходный код

Github

Я чувствую себя хорошо, дай мне звезду, спасибо ~