React-маршрутизатор смотрите здесь

внешний интерфейс сервер JavaScript React.js

предисловие

Первым проектом во фронтенде была совместная работа с коллегами по созданию крупномасштабного SPA — корпоративной серверной платформы управления.Архитектура приложения похожа на корпоративную платформу управления WeChat. React-Router, использующий стек технологий React для выполнения клиентской разработки, стал незаменимым инструментом, а переключение компонентов без обновления улучшает работу пользователей.
После прочтения многих учебных документов и практики на работе эта статья используется для подведения итогов React-Router.

решенная проблема

Маршрутизация позволяет добавлять и переключать компоненты, а также синхронизировать страницы и URL-адреса друг с другом, что широко используется в SPA. Используя React-Router, нам не нужно вручную находить компоненты, которые необходимо отрисовать, и нам не нужно писать сложную логику, просто выполните соответствующую настройку маршрутизации, а остальное оставьте для маршрутизации.

Пример

import React from 'react'
import { render } from 'react-dom'

// 首先我们需要导入一些组件...
import { Router, Route, Link } from 'react-router'

const App = React.createClass({
  render() {
    return (
      <div>
        <h1>App</h1>
        {/* 把 <a> 变成 <Link> */}
        <ul>
          <li><Link to="/about">About</Link></li>
          <li><Link to="/inbox">Inbox</Link></li>
        </ul>

        {/*
          接着用 `this.props.children` 替换 `<Child>`
          router 会帮我们找到这个 children
          childern所对应的组件可见于路由规则的嵌套关系中
          在此例中为About或Inbox或undefined
        */}
        {this.props.children}
      </div>
    )
  }
})

// 最后,我们用一些 <Route> 来渲染 <Router>。
// Router是路由容器,route为真实路由,路由之间可以进行嵌套。
// 这些就是路由提供的我们想要的东西。
React.render((
  <Router>
    <Route path="/" component={App}>
      <Route path="about" component={About} />
      <Route path="inbox" component={Inbox} />
      <Route path="messages/:id" component={Message} />
    </Route>
  </Router>
), document.body)

Маршрутизатор — это компонент React, который используется в качестве контейнера маршрутизации.Маршрут содержит правила маршрутизации. При использовании мы можем использовать иерархические отношения страниц для построения правил маршрутизации.
В Route есть два важных свойства:

  • Правило сопоставления для верхнего маршрута с атрибутом пути будет отображаться в адресной строке браузера за именем домена. Когда атрибут пути опущен, всегда загружается указанный компонент этого узла маршрута.
  • Атрибут компонента указывает компонент, который будет подключен, когда URL-адрес соответствует этому правилу маршрутизации.

С приведенной выше конфигурацией приложение будет отображать URL-адрес следующим образом:

URL компоненты
/ App
/about App -> About
/inbox App -> Inbox
/messages/[someid] App -> Message

синтаксис пути

Путь маршрута — это строковый шаблон, который соответствует URL-адресу (или его части).
Вы заметили, что третья строка правила маршрутизации немного отличается, ее путьpath="messages/:id", не указывает точно адрес маршрутизации.

В React-Router есть несколько специальных правил сопоставления:

  • :paramNameсоответствует сегменту в/,?или#после URL.
  • ()Правила внутри него являются необязательными и могут быть проигнорированы при сопоставлении.
  • *Соответствует любому символу (не жадному) до следующего символа или конца всего URL-адреса.
  <Route path="/hello/:name">         // 匹配 /hello/michael 和 /hello/ryan
  <Route path="/hello(/:name)">       // 匹配 /hello, /hello/michael 和 /hello/ryan
  <Route path="/files/*.*">           // 匹配 /files/hello.jpg 和 /files/path/to/hello.jpg

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

React.render((
  <Router>
    <Route path="/" component={App}>
      <IndexRoute component={Index} />
      <Route path="about" component={About} />
      <Route path="inbox" component={Inbox}>
        {/* 使用 /messages/:id 替换 messages/:id */}
        <Route path="/messages/:id" component={Message} />
      </Route>
    </Route>
  </Router>
), document.body)

С приведенной выше конфигурацией приложение будет отображать URL-адрес следующим образом:

URL компоненты
/ App -> Index
/about App -> About
/inbox App -> Inbox
/messages/[someid] App -> Inbox -> Message

напоминать:Абсолютные пути нельзя использовать в динамической маршрутизации.

History

React-Router построен на истории. history знает, как прослушивать изменения в адресной строке браузера, анализировать URL-адрес в объекте местоположения, а затем использовать его для сопоставления маршрута к маршрутизатору и, наконец, правильно отображать соответствующий компонент.

Обычно используются три формы истории:

  • browserHistory
  • hashHistory
  • createMemoryHistory

Способ его использования - пройти в истории:

// JavaScript 模块导入(译者注:ES6 形式)
import { browserHistory } from 'react-router'

render(
  <Router history={browserHistory} />,
  document.getElementById('app')
)

React-Router рекомендуется использоватьBrosbrowserHistoryerHistory, который использует History API в браузере для обработки URL-адреса. Сервер должен соответствующим образом сотрудничать, и сервер должен быть готов к обработке URL-адреса.
hashHistoryИспользуйте решетку (#) в URK для создания маршрута вида example.com/#/some/path .createMemoryHistoryОн используется как SSR (рендеринг на стороне сервера), который здесь подробно не обсуждается.

IndexRoute и перенаправление

IndexRoute

Когда мы переходим по ссылке какwww.demo.html/, страница загрузит компонент приложения. Но в настоящее время this.props.children в рендеринге приложения не определен, потому что наш маршрут не соответствует дочерним компонентам приложения. В этот момент мы можем использоватьIndexRouteустановить страницу по умолчанию. Модифицированный маршрут выглядит следующим образом:

React.render((
  <Router>
    <Route path="/" component={App}>
      <IndexRoute component={Index}>
      <Route path="about" component={About} />
      <Route path="inbox" component={Inbox} />
      <Route path="messages/:id" component={Message} />
    </Route>
  </Router>
), document.body)

На этом этапе this.props.children в рендеринге приложения будет компонентом.

Redirect

Рассмотрим проблему, если в адресной строке вводится URL, не совпадающий с правилом маршрутизации, напримерwww.demo.html/#/noroute,Что случится? Страница будет пустой и пустой.
У нас есть такая потребность посетитьwww.demo.html/#/inboxкогда я хочу, чтобы адрес перешел кwww.demo.html/#/about, визуализируйте компонент «О программе» или исправьте пустую ошибку выше и перейдите к компоненту «О программе».
Чтобы решить такую ​​проблему, мы можем использовать Redirect для перенаправления.

React.render((
  <Router>
    <Route path="/" component={App}>
      <IndexRoute component={Index}>
      <Route path="about" component={About} />
      <Route path="inbox" component={Inbox} />
      <Route path="messages/:id" component={Message} />
      {/* 跳转 /inbox 到 /about */}
      <Redirect from="inbox" to="about" />
    </Route>
  </Router>
), document.body)

прыжок по маршруту

Переходы маршрутизации можно разделить на внутренние переходы и внешние переходы.Ссылки используются для завершения внутренних переходов, и принцип тот же, что и у метки. Выйти за пределы компонента можно с помощью метода push.

Link

Компонент Link используется для замены тега a для создания ссылки, которая позволяет пользователю перейти на другой маршрут после нажатия, как это используется в случае использования. Свойство activeStyle может добавлять стили к текущему маршруту. Или используйте activeClassName, чтобы добавить класс к текущему маршруту.

<Link to="/about" activeStyle={{color: 'red'}}>About</Link>
<Link to="/inbox" activeStyle={{color: 'green'}}>Inbox</Link>

push

Нам нужно прыгать, когда форма отправлена ​​и нажата кнопка, мы можем использовать метод push для его завершения.

// somewhere like a redux/flux action file:
import { browserHistory } from 'react-router'
browserHistory.push('/some/path')

IndexLink

Если вы используете в этом приложении<Link to="/">Home</Link>, он всегда будет активен, activeStyle и activeClassName будут недействительными или будут действовать всегда. Поскольку все правила маршрутизации начинаются с / . Это действительно проблема, потому что мы хотим, чтобы Дом был активирован и связан с ним только после его рендеринга. Если вам нужна ссылка на / которая активируется после отрисовки Home route, то есть для достижения точного совпадения,/Чтобы соответствовать только корневому маршруту, вы можете использовать<IndexLink to="/">Home</IndexLink>.

Или используйте свойство onlyActiveOnIndex компонента Link для достижения того же эффекта.

<Link to="/" activeClassName="active" onlyActiveOnIndex={true}>
  Home
</Link>

динамическая маршрутизация

React-Router (версия 4) реализует динамическую маршрутизацию.

Для больших приложений одной из первых проблем является размер кода JavaScript, который необходимо загрузить. Программа должна загружать только тот JavaScript, который необходим для рендеринга страницы в данный момент. Некоторые разработчики называют этот подход «разделением кода» — разделением всего кода на несколько небольших пакетов, которые загружаются по запросу, пока пользователь просматривает сайт. Сопоставление путей и загрузка компонентов в React-Router выполняются асинхронно, что позволяет вам не только лениво загружать компоненты, но и лениво загружать конфигурацию маршрутизации. Route может определять функции getChildRoutes, getIndexRoute и getComponents. Все они выполняются асинхронно и вызываются только при необходимости. Мы называем этот подход «постепенным сопоставлением». React-Router будет постепенно сопоставлять URL-адрес и загружать только конфигурацию пути и компоненты, необходимые для страницы, соответствующей URL-адресу.

const CourseRoute = {
  path: 'course/:courseId',

  getChildRoutes(location, callback) {
    require.ensure([], function (require) {
      callback(null, [
        require('./routes/Announcements'),
        require('./routes/Assignments'),
        require('./routes/Grades'),
      ])
    })
  },

  getIndexRoute(location, callback) {
    require.ensure([], function (require) {
      callback(null, require('./components/Index'))
    })
  },

  getComponents(location, callback) {
    require.ensure([], function (require) {
      callback(null, require('./components/Course'))
    })
  }
}

Хуки жизненного цикла хуков

Маршрут может определить две ловушки, onEnter и onLeave, которые используются для захвата моментов времени входа и выхода из маршрута, а также для выполнения некоторых операций, таких как завершение проверки разрешений.

В процессе перехода маршрута хук onLeave будет срабатывать во всех маршрутах, которые будут уходить, начиная с самого нижнего дочернего маршрута и заканчивая самым внешним родительским маршрутом. Затем хук onEnter будет начинаться с самого внешнего родительского маршрута до конца самого нижнего дочернего маршрута. Тот же механизм, что и для захвата событий и всплывающих сообщений.

<Router>
    <Route path="about" component={About} onEnter={/*dosomething*/} />
    <Route path="inbox" component={Inbox}>
      <Redirect from="messages/:id" to="/messages/:id" onLeave={/*dosomething*/} />
    </Route>
  </Router>

В приведенном выше коде, если пользователь покидает /messages/:id и вводит /about, по очереди будут срабатывать следующие хуки.

/messages/:id的onLeave
/inbox的onLeave
/about的onEnter

routerWillLeaveявляется крюком жизненного цикла при выходе из текущего маршрута. Если этот метод возвращает false, он предотвратит переключение маршрута, в противном случае он вернет строку, которая запрашивает у пользователя подтверждение перед выходом из маршрута.

import { Lifecycle } from 'react-router'

const Home = React.createClass({

  // 假设 Home 是一个 route 组件,它可能会使用
  // Lifecycle mixin 去获得一个 routerWillLeave 方法。
  mixins: [ Lifecycle ],

  routerWillLeave(nextLocation) {
    if (!this.state.isSaved)
      return 'Your work is not saved! Are you sure you want to leave?'
  },

  // ...

})

Corner

  • Алгоритм маршрутизации сопоставляет маршруты сверху вниз в соответствии с заданным порядком, сопоставляя первый маршрут, соответствующий правилу.
  • в состоянии пройтиthis.props.params.idполучить/:idидентификатор в .
  • Строка запроса URL /foo?bar=baz может использоваться сthis.props.location.query.barПолучать.