Обратите внимание, что этот ответ касается React Router версии 0.13.x - похоже, что в грядущей версии 1.0 будут значительно отличаться детали реализации.
Сервер
Это минимум server.jsс реактивным маршрутизатором:
var express = require('express')
var React = require('react')
var Router = require('react-router')
var routes = require('./routes')
var app = express()
// ...express config...
app.use(function(req, res, next) {
var router = Router.create({location: req.url, routes: routes})
router.run(function(Handler, state) {
var html = React.renderToString(<Handler/>)
return res.render('react_page', {html: html})
})
})
Где routesмодуль экспортирует список маршрутов:
var React = require('react')
var {DefaultRoute, NotFoundRoute, Route} = require('react-router')
module.exports = [
<Route path="/" handler={require('./components/App')}>
{/* ... */}
</Route>
]
Каждый раз, когда делается запрос к серверу, вы создаете одноразовый Routerэкземпляр, настроенный с входящим URL-адресом в качестве статического местоположения, которое разрешается в дереве маршрутов для настройки соответствующих сопоставленных маршрутов, вызывая ответ с помощью верхнего уровня обработчик маршрута, который необходимо отобразить, и запись о том, какие дочерние маршруты совпадают на каждом уровне. Это то, к чему вы обращаетесь при использовании<RouteHandler> компонент в компоненте обработки маршрута для визуализации дочернего маршрута, который был сопоставлен.
Если у пользователя отключен JavaScript или он медленно загружается, любые ссылки, по которым он нажимает, снова попадут на сервер, что снова разрешится, как указано выше.
Клиент
Это минимум client.jsс реактивным маршрутизатором (повторное использование того же модуля маршрутов):
var React = require('react')
var Router = require('react-router')
var routes = require('./routes')
Router.run(routes, Router.HistoryLocation, function(Handler, state) {
React.render(<Handler/>, document.body)
})
Когда ты звонишь Router.run() , он создает для вас за кулисами экземпляр Router, который повторно используется каждый раз, когда вы перемещаетесь по приложению, поскольку URL-адрес может быть динамическим на клиенте, в отличие от сервера, где один запрос имеет фиксированный URL.
В этом случае мы используем HistoryLocation, который использует HistoryAPI, чтобы убедиться, что все происходит правильно, когда вы нажимаете кнопку назад / вперед. Также есть, HashLocationкоторый изменяет URL-адрес hashдля создания записей в истории и прослушивает window.onhashchangeсобытие для запуска навигации.
Когда вы используете <Link>компонент response-router , вы даете ему toопору, которая представляет собой имя маршрута, а также любые данные paramsи queryданные, необходимые для маршрута. <a>Оказываемое этот компонент имеет onClickобработчик , который в конечном счете вызывает router.transitionTo()на экземпляре маршрутизатора с реквизитом вы дали ссылку, которая выглядит следующим образом :
/**
* Transitions to the URL specified in the arguments by pushing
* a new URL onto the history stack.
*/
transitionTo: function (to, params, query) {
var path = this.makePath(to, params, query);
if (pendingTransition) {
// Replace so pending location does not stay in history.
location.replace(path);
} else {
location.push(path);
}
},
Для обычной ссылки это в конечном итоге вызывает location.push()любой тип местоположения, который вы используете, который обрабатывает детали настройки истории, поэтому навигация с помощью кнопок назад и вперед будет работать, а затем обратный вызов, router.handleLocationChange()чтобы сообщить маршрутизатору, что он может перейти к новый путь URL.
Затем маршрутизатор вызывает свой собственный router.dispatch()метод с новым URL-адресом, который обрабатывает детали определения того, какой из настроенных маршрутов соответствует URL-адресу, а затем вызывает любые перехватчики перехода. имеющиеся для сопоставленных маршрутов. Вы можете реализовать эти перехватчики перехода на любом из ваших обработчиков маршрутов, чтобы предпринять некоторые действия, когда маршрут должен быть отклонен от маршрута или перемещен к нему, с возможностью прервать переход, если вам что-то не нравится.
Если переход не был прерван, последний шаг - вызвать обратный вызов, который вы передали Router.run()с помощью компонента обработчика верхнего уровня и объекта состояния со всеми подробностями URL-адреса и согласованных маршрутов. Компонент обработчика верхнего уровня на самом деле является Routerсамим экземпляром, который обрабатывает отображение самого верхнего обработчика маршрута, который был сопоставлен.
Вышеупомянутый процесс повторно запускается каждый раз, когда вы переходите к новому URL-адресу на клиенте.
Примеры проектов