[Aktualizacja]
Po pracy na pęczek React/aplikacji topnika, doszedłem do wniosku, że wolę routingu być traktowane oddzielnie i prostopadle do topnika. Strategia polega na tym, że adresy URL/trasy powinny określać, które komponenty są montowane, a komponenty żądają danych ze sklepów na podstawie parametrów trasy i, w razie potrzeby, innego stanu aplikacji.
[Original Odpowiedź]
Podejście wziąłem z ostatnim projekcie podczas eksperymentowania z Flux było wykonanie warstwy routingu tylko kolejny sklep. Oznacza to, że wszystkie linki, które zmieniają adres URL, faktycznie wywołują akcję za pośrednictwem kontrolera żądającego uaktualnienia trasy. Odpowiedź na tę wiadomość została przesłana na adres RouteStore
, ustawiając adres URL w przeglądarce i ustawiając niektóre dane wewnętrzne (przez route-recognizer), aby widoki mogły wysyłać zapytania do nowych danych routingu po zdarzeniu ze sklepu ze zdarzenia change
.
Jednym z nieoczywistych elementów dla mnie było to, jak zapewnić, że zmiany URL wywołały akcje; Skończyło się na tym, że utworzyłem mixin, aby to sobie poradzić (uwaga: to nie jest w 100% niezawodne, ale działało dla aplikacji, z której korzystałem, być może będziesz musiał wprowadzić modyfikacje dostosowane do twoich potrzeb).
// 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's 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);
}
}
};
Byłoby być używany jako tak:
var ApplicationView = React.createClass({
mixins: [RoutingMixin],
handleRouteChange: function(newUrl, fromHistory) {
this.dispatcher.dispatch(RouteActions.changeUrl(newUrl, fromHistory));
},
// ...
});
procedury obsługi w sklepie może wyglądać:
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");
}
}
mógłbyś wyjaśnić co masz na myśli, przechodząc między stanami w swoje pytanie? Myślę, że nie masz na myśli stanu aplikacji, ale raczej poruszania się między adresami URL tras/SPA. Jeśli tak, Flux jest jedynie architekturą aplikacji, która opisuje komunikację między aplikacjami i kontrolę. Społeczność Flux ogólnie zdecydowała, że routing jest poza zakresem i zobacz odpowiedź Nacho na re: router reagowania. –