Dengan menggunakan Backbone, apakah saya bisa mendapatkan nama untuk rute saat ini? Saya tahu cara mengikat ke peristiwa perubahan rute, tetapi saya ingin dapat menentukan rute saat ini di waktu lain, di antara perubahan.
backbone.js
Drew Dara-Abrams
sumber
sumber
Jawaban:
Jika Anda telah membuat instance Router di aplikasi Anda, baris berikut menampilkan fragmen saat ini:
Dari dokumentasi Backbone.js :
"[...] Histori berfungsi sebagai router global (per frame) untuk menangani peristiwa hashchange atau pushState, mencocokkan rute yang sesuai, dan memicu callback. Anda tidak perlu membuat sendiri salah satunya - Anda harus menggunakan referensi ke Backbone.history yang akan dibuat untuk Anda secara otomatis jika Anda menggunakan Router dengan rute. [...] "
Jika Anda membutuhkan nama fungsi yang terikat ke fragmen itu, Anda dapat membuat sesuatu seperti ini di dalam cakupan Router Anda:
alert( this.routes[Backbone.history.getFragment()] );
Atau seperti ini dari luar router Anda:
sumber
Backbone.history.getFragment()
, karenaBackbone.history.fragment
merupakan properti tersembunyi pribadi.Jawaban Robert menarik, tetapi sayangnya itu hanya akan berfungsi jika hash persis seperti yang ditentukan dalam rute. Misalnya, jika Anda memiliki rute untuk
user(/:uid)
itu tidak akan cocok jikaBackbone.history.fragment
adalah salah satu"user"
atau"user/1"
(keduanya merupakan dua kasus penggunaan paling jelas untuk rute tersebut). Dengan kata lain, ini hanya akan menemukan nama panggilan balik yang sesuai jika hashnya sama persis"user(/:uid)"
(sangat tidak mungkin).Karena saya membutuhkan fungsi ini saya memperpanjang
Backbone.Router
dengancurrent
-fungsi yang menggunakan kembali beberapa kode yang digunakan objek History dan Router untuk mencocokkan fragmen saat ini terhadap Rute yang ditentukan untuk memicu callback yang sesuai. Untuk kasus penggunaan saya, dibutuhkan parameter opsionalroute
, yang jika disetel ke sesuatu yang benar akan mengembalikan nama fungsi yang sesuai yang ditentukan untuk rute tersebut. Jika tidak, ini akan mengembalikan fragmen hash saat ini dariBackbone.History.fragment
.Anda dapat menambahkan kode ke Perpanjang yang ada tempat Anda menginisialisasi dan menyiapkan 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'
Saya yakin beberapa perbaikan dapat dilakukan, tetapi ini adalah cara yang baik untuk Anda mulai. Juga, mudah untuk membuat fungsionalitas ini tanpa memperluas objek Route. Saya melakukan ini karena ini adalah cara paling nyaman untuk pengaturan saya.
Saya belum menguji ini sepenuhnya, jadi tolong beri tahu saya jika ada yang tidak beres.
UPDATE 04/25/2013
Saya melakukan beberapa perubahan pada fungsi, jadi alih-alih mengembalikan hash atau nama panggilan balik rute, saya mengembalikan objek dengan fragmen, params, dan rute sehingga Anda dapat mengakses semua data dari rute saat ini, seperti yang Anda lakukan dari rute- peristiwa.
Anda dapat melihat perubahan di bawah ini:
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 }; }
Lihat kode sebelumnya untuk komentar dan penjelasan lebih lanjut, sebagian besar terlihat sama.
sumber
_.find
fungsi sebagaithis
, sehingga menghilangkan kebutuhan akanRouter
variabel (@DanAbramov sudah melakukan ini).Marionette.AppRouter
, memperpanjang router Anda dengan fungsi di atas, tetapi penggantiRouter.appRoutes
untukRouter.routes
.Untuk mendapatkan rute panggilan (atau url) dari penangan rute yang disebut, Anda bisa mendapatkannya dengan memeriksa
Saya sampai di sini untuk mencari jawaban ini jadi saya rasa saya harus meninggalkan apa yang saya temukan.
sumber
Jika Anda menggunakan pengaturan root untuk Router, Anda juga dapat memasukkannya untuk mendapatkan fragmen 'asli'.
(Backbone.history.options.root || "") + "/" + Backbone.history.fragment
sumber
Berikut adalah anak laki-laki lebih verbose (atau, tergantung selera Anda, lebih mudah dibaca) versi jawaban Simon :
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 }; } }
sumber
Jika Anda melihat sumber untuk
Router
, Anda akan melihat bahwa ketika router memicu peristiwa yang mengatakan bahwa ada sesuatu yang berubah, ia meneruskan namanya sebagai "route: name".http://documentcloud.github.com/backbone/docs/backbone.html#section-84
Anda selalu dapat mengaitkan peristiwa "rute" di router dan menyimpannya untuk mendapatkan rute saat ini.
sumber
route
acara jikatrigger
tidaktrue
(disarankan & default).router = new Backbone.Router.extend({ routes: { "stuff/:id" : "stuff" }, stuff: function(id) {} }); router.on('route', function(route) { this.current = route; });
Sekarang jika Anda menavigasi ke
/stuff/1
, router.current akan menjadi "barang"sumber