Обратите внимание, что этот ответ касается 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
, который использует History
API, чтобы убедиться, что все происходит правильно, когда вы нажимаете кнопку назад / вперед. Также есть, 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-адресу на клиенте.
Примеры проектов