Czy za pomocą Backbone mogę uzyskać nazwę bieżącej trasy? Wiem, jak powiązać zdarzenia zmiany trasy, ale chciałbym móc określić bieżącą trasę w innym czasie, pomiędzy zmianami.
Czy za pomocą Backbone mogę uzyskać nazwę bieżącej trasy? Wiem, jak powiązać zdarzenia zmiany trasy, ale chciałbym móc określić bieżącą trasę w innym czasie, pomiędzy zmianami.
Odpowiedzi:
Jeśli utworzyłeś wystąpienie routera w swojej aplikacji, poniższy wiersz zwraca bieżący fragment:
Backbone.history.getFragment();
„[...] Historia służy jako router globalny (na ramkę) do obsługi zdarzeń związanych z hashchange lub pushState, dopasowywania odpowiedniej trasy i wywoływania wywołań zwrotnych. Nigdy nie powinno być konieczne samodzielne tworzenie jednego z nich - należy użyć odniesienia do Backbone.history, który zostanie utworzony automatycznie, jeśli użyjesz routerów z trasami. [...] "
Jeśli potrzebujesz nazwy funkcji związanej z tym fragmentem, możesz zrobić coś takiego w zasięgu routera:
alert( this.routes[Backbone.history.getFragment()] );
Lub w ten sposób spoza routera:
alert( myRouter.routes[Backbone.history.getFragment()] );
Backbone.history.getFragment(), ponieważ Backbone.history.fragmentjest to prywatna ukryta własność.
Odpowiedź Roberta jest interesująca, ale niestety zadziała tylko wtedy, gdy hash jest dokładnie taki, jak zdefiniowano w trasie. Jeśli na przykład masz trasę, user(/:uid)nie zostanie ona dopasowana, jeśli Backbone.history.fragmentjest to albo "user"albo "user/1"(oba są dwoma najbardziej oczywistymi przypadkami użycia takiej trasy). Innymi słowy, znajdzie odpowiednią nazwę wywołania zwrotnego tylko wtedy, gdy hash jest dokładnie "user(/:uid)"(bardzo mało prawdopodobne).
Ponieważ potrzebowałem tej funkcjonalności, rozszerzyłem funkcję Backbone.Routera, currentktóra ponownie wykorzystuje część kodu używanego przez obiekt Historia i Router w celu dopasowania bieżącego fragmentu do zdefiniowanych tras w celu wyzwolenia odpowiedniego wywołania zwrotnego. W moim przypadku przyjmuje opcjonalny parametr route, który, jeśli jest ustawiony na cokolwiek prawdziwe, zwróci odpowiednią nazwę funkcji zdefiniowaną dla trasy. W przeciwnym razie będzie to powrót aktualny hash-fragment z Backbone.History.fragment.
Możesz dodać kod do istniejącego rozszerzenia Extend, w którym zainicjujesz i skonfigurujesz router Backbone.
var Router = new Backbone.Router.extend({
// Pretty basic stuff
routes : {
"home" : "home",
"user(:/uid)" : "user",
"test" : "completelyDifferent"
},
home : function() {
// Home route
},
user : function(uid) {
// User route
},
// Gets the current route callback function name
// or current hash fragment
current : function(route){
if(route && Backbone.History.started) {
var Router = this,
// Get current fragment from Backbone.History
fragment = Backbone.history.fragment,
// Get current object of routes and convert to array-pairs
routes = _.pairs(Router.routes);
// Loop through array pairs and return
// array on first truthful match.
var matched = _.find(routes, function(handler) {
var route = handler[0];
// Convert the route to RegExp using the
// Backbone Router's internal convert
// function (if it already isn't a RegExp)
route = _.isRegExp(route) ? route : Router._routeToRegExp(route);
// Test the regexp against the current fragment
return route.test(fragment);
});
// Returns callback name or false if
// no matches are found
return matched ? matched[1] : false;
} else {
// Just return current hash fragment in History
return Backbone.history.fragment
}
}
});
// Example uses:
// Location: /home
// console.log(Router.current()) // Outputs 'home'
// Location: /user/1
// console.log(Router.current(true)) // Outputs 'user'
// Location: /user/2
// console.log(Router.current()) // Outputs 'user/2'
// Location: /test
// console.log(Router.current(true)) // Outputs 'completelyDifferent'
Jestem pewien, że można by wprowadzić pewne ulepszenia, ale to dobry sposób na rozpoczęcie. Ponadto łatwo jest stworzyć tę funkcjonalność bez rozszerzania obiektu Route. Zrobiłem to, ponieważ był to najwygodniejszy sposób na moją konfigurację.
Nie testowałem tego jeszcze w pełni, więc daj mi znać, jeśli coś pójdzie na południe.
Dokonałem pewnych zmian w funkcji, więc zamiast zwracać nazwę skrótu lub wywołania zwrotnego trasy, zwracam obiekt z fragmentem, parametrami i trasą, dzięki czemu można uzyskać dostęp do wszystkich danych z bieżącej trasy, podobnie jak w przypadku trasy- zdarzenie.
Możesz zobaczyć zmiany poniżej:
current : function() {
var Router = this,
fragment = Backbone.history.fragment,
routes = _.pairs(Router.routes),
route = null, params = null, matched;
matched = _.find(routes, function(handler) {
route = _.isRegExp(handler[0]) ? handler[0] : Router._routeToRegExp(handler[0]);
return route.test(fragment);
});
if(matched) {
// NEW: Extracts the params using the internal
// function _extractParameters
params = Router._extractParameters(route, fragment);
route = matched[1];
}
return {
route : route,
fragment : fragment,
params : params
};
}
Zobacz poprzedni kod, aby uzyskać dalsze komentarze i wyjaśnienia, wyglądają one w większości tak samo.
_.findfunkcji jako this, eliminując tym samym potrzebę Routerzmiennej (@DanAbramov już to zrobił).
Marionette.AppRouterprzedłużyć swój router z funkcją powyżej, jednak substytut Router.appRoutesdla Router.routes.
Aby uzyskać trasę wywołującą (lub adres URL) z wywoływanej procedury obsługi trasy, możesz ją uzyskać, zaznaczając
Backbone.history.location.href ... pełny adres URL Backbone.history.location.search ... ciąg zapytania zaczynający się od?
Dotarłem tutaj w poszukiwaniu tej odpowiedzi, więc myślę, że powinienem zostawić to, co znalazłem.
Jeśli używasz ustawienia root dla routera, możesz je również dołączyć, aby uzyskać „prawdziwy” fragment.
(Backbone.history.options.root || "") + "/" + Backbone.history.fragment
Oto odrobinę bardziej rozwlekła (lub, w zależności od gustu, bardziej czytelna) wersja odpowiedzi Simona :
current: function () {
var fragment = Backbone.history.fragment,
routes = _.pairs(this.routes),
route,
name,
found;
found = _.find(routes, function (namedRoute) {
route = namedRoute[0];
name = namedRoute[1];
if (!_.isRegExp(route)) {
route = this._routeToRegExp(route);
}
return route.test(fragment);
}, this);
if (found) {
return {
name: name,
params: this._extractParameters(route, fragment),
fragment: fragment
};
}
}
Jeśli spojrzysz na źródło Router, zobaczysz, że kiedy router wyzwala zdarzenie, mówiąc, że coś się zmienia, przekazuje mu nazwę jako „route: name”.
http://documentcloud.github.com/backbone/docs/backbone.html#section-84
Zawsze możesz podpiąć zdarzenie „route” do routera i zapisać je w celu uzyskania aktualnej trasy.
routezdarzenia, jeśli trigger nie jest true (zalecane i domyślne).