Маршрутизация клиента (с помощью react-router) и маршрутизация на стороне сервера



Я думал, и я запутался с маршрутизацией между клиентом и сервером. Предположим, что я использую ReactJS для рендеринга на стороне сервера перед отправкой запроса обратно в веб-браузер и использую react-router в качестве маршрутизации на стороне клиента для переключения между страницами без обновления как SPA.



что приходит на ум, это:




  • как интерпретируются маршруты? Например, запрос с домашней страницы (/home) на страницу сообщений (/posts)

  • причем тут маршрутизация перейти, на стороне сервера или клиента?

  • как он знает, как он обрабатывается?

745   2  

2 ответов:

обратите внимание, этот ответ охватывает реагируют версии маршрутизатора 0.13.х -следующей версии 1.0 похоже, что он будет иметь значительно разные детали реализации

сервер

это минимальный server.js С react-router:

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 или он медленно загружается, любые ссылки, которые они нажимают on снова ударит по серверу, который снова будет разрешен, как указано выше.

клиент

это минимальный client.js С react-router (повторное использование того же модуля маршрутов):

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(), он создает экземпляр маршрутизатора для вас за кулисами, который повторно используется каждый раз, когда вы перемещаетесь по приложению, поскольку URL-адрес может быть динамическим на клиенте, а не на сервере, где один запрос имеет фиксированный URL-адрес.

в этом случае, мы используем HistoryLocation, который использует History API чтобы убедиться, что правильная вещь происходит, когда вы нажмете кнопку Назад/Вперед. Там также есть HashLocation который изменяет URL hash чтобы сделать записи истории и слушает window.onhashchange событие для запуска навигации.

при использовании react-router's <Link> компонент, вы даете ему 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 на сайте клиент.

примеры проектов

С 1.0, React-маршрутизатор зависит от история модуль как peerDependency. Этот модуль занимается маршрутизацией в браузере. По умолчанию React-Router использует HTML5 History API (pushState,replaceState), но вы можете настроить его на использование маршрутизации на основе хэша (см. ниже)

обработка маршрута теперь выполняется за кулисами, и ReactRouter отправляет новые реквизиты вниз к обработчикам маршрута при изменении маршрута. Маршрутизатор имеет новый onUpdate prop обратный вызов всякий раз, когда маршрут изменения, полезные для отслеживания просмотров страниц или обновления <title>, например.

клиент (маршрутизация HTML5)

import {Router} from 'react-router'
import routes from './routes'

var el = document.getElementById('root')

function track(){
  // ...
}

// routes can be children
render(<Router onUpdate={track}>{routes}</Router>, el)

клиент (маршрутизация на основе хэша)

import {Router} from 'react-router'
import {createHashHistory} from 'history'
import routes from './routes'

var el = document.getElementById('root')

var history = createHashHistory()

// or routes can be a prop
render(<Router routes={routes} history={history}></Router>, el)

сервер

на сервере, мы можем использовать ReactRouter.match, это взято из руководство по рендерингу сервера

import { renderToString } from 'react-dom/server'
import { match, RoutingContext } from 'react-router'
import routes from './routes'

app.get('*', function(req, res) {
  // Note that req.url here should be the full URL path from
  // the original request, including the query string.
  match({ routes, location: req.url }, (error, redirectLocation, renderProps) => {
    if (error) {
      res.status(500).send(error.message)
    } else if (redirectLocation) {
      res.redirect(302, redirectLocation.pathname + redirectLocation.search)
    } else if (renderProps) {
      res.status(200).send(renderToString(<RoutingContext {...renderProps} />))
    } else {
      res.status(404).send('Not found')
    }
  })
})

Comments

    Ничего не найдено.