Подтвердить что ты не робот

В архитектуре Flux, как вы управляете состояниями маршрутизации /url на стороне клиента?

В качестве ответа на вопрос Сохранять жизненный цикл,

В обычном веб-приложении приятно иметь ярлык для текущего состояния приложения через URL-адрес, чтобы вы могли повторно посетить это состояние и использовать кнопки "вперед" и "назад" для перемещения между состояниями.

С Flux мы хотим, чтобы все действия проходили через диспетчера, который, как я полагаю, также включает изменение URL. как бы вы управляли изменениями URL-адресов в приложении потока?

4b9b3361

Ответ 1

[Обновление]

После работы над связью приложений React/Flux я пришел к выводу, что предпочитаю, чтобы маршрутизация обрабатывалась отдельно и ортогонально потоку. Стратегия заключается в том, что URL/маршруты должны определять, какие компоненты устанавливаются, а компоненты запрашивают данные из магазинов на основе параметров маршрута и другого состояния приложения по мере необходимости.

[Оригинальный ответ]

Подход, который я использовал в недавнем проекте при экспериментировании с Flux, заключался в том, чтобы сделать слой маршрутизации только другим хранилищем. Это означает, что все ссылки, которые изменяют URL-адрес, фактически инициируют действие через диспетчера, требуя обновления маршрута. A RouteStore ответил на эту отправку, установив URL-адрес в браузере и установив некоторые внутренние данные (через route-recognizer), чтобы представления могли запрашивать новые данные маршрутизации при событии change, запущенном из магазина.

Одна неочевидная часть для меня заключалась в том, как обеспечить действия по изменению URL-адресов; Я закончил создание mixin для управления этим для меня (обратите внимание: это не на 100% надежный, но работал на приложение, которое я использовал, возможно, вам придется внести изменения в соответствии с вашими потребностями).

// Mix-in to the top-level component to capture `click`
// events on all links and turn them into action dispatches;
// also manage HTML5 history via pushState/popState
var RoutingMixin = {
  componentDidMount: function() {
    // Some browsers have some weirdness with firing an extra 'popState'
    // right when the page loads
    var firstPopState = true;

    // Intercept all bubbled click events on the app element
    this.getDOMNode().addEventListener('click', this._handleRouteClick);

    window.onpopstate = function(e) {
      if (firstPopState) {
        firstPopState = false;
        return;
      }
      var path = document.location.toString().replace(document.location.origin, '');
      this.handleRouteChange(path, true);
    }.bind(this);
  },

  componentWillUnmount: function() {
    this.getDOMNode().removeEventListener('click', this._handleRouteClick);
    window.onpopstate = null;
  },

  _handleRouteClick: function(e) {
    var target = e.target;

    // figure out if we clicked on an `a` tag
    while(target && target.tagName !== 'A') {
      target = target.parentNode;
    }

    if (!target) return;

    // if the user was holding a modifier key, don't intercept
    if (!e.altKey && !e.ctrlKey && !e.shiftKey && !e.metaKey) {
      e.preventDefault();

      var href = target.attributes.href.value;
      this.handleRouteChange(href, false);
    }
  }
};

Он будет использоваться так:

var ApplicationView = React.createClass({
  mixins: [RoutingMixin],

  handleRouteChange: function(newUrl, fromHistory) {
    this.dispatcher.dispatch(RouteActions.changeUrl(newUrl, fromHistory));
  },

  // ...
});

Обработчик в магазине может выглядеть примерно так:

RouteStore.prototype.handleChangeUrl = function(href, skipHistory) {
  var isFullUrl = function(url) {
    return url.indexOf('http://') === 0 || url.indexOf('https://') === 0;
  }

  // links with a protocol simply change the location
  if (isFullUrl(href)) {
    document.location = href;
  } else {
    // this._router is a route-recognizer instance
    var results = this._router.recognize(href);
    if (results && results.length) {
      var route = results[0].handler(href, results[0].params);
      this.currentRoute = route;
      if (!skipHistory) history.pushState(href, '', href);
    }

    this.emit("change");
  }
}

Ответ 2

В большинстве примеров в дикой природе используйте React Router, структуру, основанную на маршрутизаторе Ember. Важной частью является конфигурация маршрутов как декларативная спецификация компонентов:

React.render((
  <Router>
    <Route path="/" component={App}>
      <Route path="about" component={About}/>
      <Route path="users" component={Users}>
        <Route path="/user/:userId" component={User}/>
      </Route>
      <Redirect from="/" to="about" />
      <NotFoundRoute handler={NoMatch} />
    </Route>
  </Router>
), document.body)