Tôi muốn có một phương pháp thiết lập/teardown được gọi trước và sau khi một tuyến đường được kích hoạt trong bộ định tuyến Backbone.js của tôi, tương ứng. Có ai tạo ra một cách thanh lịch để làm điều này?Backbone.js - Phương thức gọi trước/sau khi một tuyến đường được kích hoạt
Trả lời
_.wrap không phải là giải pháp, nếu bạn có ví dụ 20 tuyến đường bạn phải gói tất cả.
Nhưng bạn có thể làm điều này với lập trình meta
class Backbone.FlexRouter extends Backbone.Router
route: (route, name, handler) ->
super route, name, ->
@trigger "route:before"
handler()
@trigger "route:after"
UPD: Tôi tin vào JS nó phải được một cái gì đó như thế này (nhưng tôi đã không kiểm tra nó)
var rp = Backbone.Router.prototype
rp.routeWithoutEvents = rp.route
rp.route = function(route, name, handler){
var that = this
this.routeWithoutEvents(route, name, function(){
that.trigger("route:before")
handler()
that.trigger("route:after")
})
}
Bạn đã xem _.wrap chưa?
Plugin này làm gì bạn muốn. Nó hoạt động với 0.5.3. Tôi không chắc chắn nếu nó hoạt động với 0.9.1 được nêu ra hay không.
Alexey của câu trả lời là gần như ngay, nhưng có một vài điều tế nhị mà đang thiếu.
class ApplicationRouter extends Backbone.Router
route: (route, name, callback = null) ->
callback = @[name] if ! callback
super route, name, ->
@trigger 'route:before'
result = callback && callback.apply(@, arguments)
@trigger 'route:after'
return result
Câu trả lời của bạn chính xác hơn, nhưng nó có thể không hoạt động vì không thể cung cấp tính năng gọi lại. Trong trường hợp đó, phương thức route theo mặc định sẽ tìm một hàm có tên là tên route (xem mã trong câu trả lời của tôi). –
@AmebaSpugnosa dòng này xử lý, vì vậy tôi không chắc chắn những gì bạn có nghĩa là: 'callback = @ [name] if! callback' –
Nếu bạn đi trên mã nguồn Backbone.js, bạn sẽ thấy rằng Router.route không chỉ chuẩn bị một cuộc gọi đơn giản. Các cuộc gọi lại chính nó, trong điều kiện nhất định, có thể được tìm thấy bằng cách đặt tên quy ước và không phải bằng cách tham khảo đi qua. Đó là lý do tại sao bạn không thể chỉ quấn nó như bạn đã làm. –
Tôi đã gặp vấn đề này trước đó và tôi nghĩ mình sẽ chia sẻ giải pháp của mình để chèn "phần mềm trung gian" vào luồng định tuyến Backbone. Mục đích là để định tuyến lại người dùng các dòng khác nhau tùy thuộc vào một số điều kiện, ví dụ như, cờ tính năng, xử lý phiên làm việc, vv ..
Backbone.ProtectedRouter = Backbone.Router.extend({
/*
* Subclass of Router that monkeypatches route in order to protect certain
* routes.
*
* If you want to add a protected route, add it to the protectedRoutes
* object in this form:
* route: { method: fn, assertion: fn, args: [args..] }
*
* * method => the method to call if the assertion is true (the route should
* be protected in the given scenario)
*
* * assertion => the function that decides whether or not the route
* should be rendered
*
* * args => the arguments to be passed to method
*/
route: function(route, name, handler) {
var _this = this;
Backbone.Router.prototype.route(route, name, function(){
var boundHandler = _.bind(handler, _this),
attrs, method, args, dfd;
attrs = _.has(_this.protectedRoutes, route) ? _this.protectedRoutes[route] : null;
if (attrs && !attrs.assertion()) {
// In this scenario my flows all return Deferreds
// you can make this event based as well.
dfd = _this[attrs.method].apply(_this, attrs.args.concat([route]));
dfd.then(boundHandler);
} else
boundHandler.apply(_this, arguments);
});
}
});
Từ đó bạn có thể dễ dàng mở rộng Backbone.ProtectedRouter
với một hash protectedRoutes
như vậy:
var router = Backbone.ProtectedRouter.extend({
protectedRoutes: {
'home': {
assertion: function() { return is_logged_in; },
method: 'renderLogin',
args: ['some_arg']
}
},
routes: {
'home': 'renderHome'
},
...
});
Trong tình huống này, nếu yêu cầu được thực hiện cho con đường home
và is_logged_in
là false
, phương pháp renderLogin
được gọi và thông qua 'some_arg'
. Sau khi luồng, renderLogin
sẽ trả về Trì hoãn đã giải quyết khiến trình xử lý ban đầu (renderHome
) được gọi.
Tôi hy vọng điều này sẽ hữu ích. Tôi cũng rất cởi mở với các đề xuất! :)
Tôi đã xem xét nhu cầu này gần đây (để kiểm tra người dùng được xác thực). Thật không may Backbone không cung cấp cho chúng ta một sự kiện trước/sau, vì vậy bạn sẽ cần phải ghi đè hoặc mở rộng Router.route. Không cảm thấy rất sạch sẽ vì bạn phải sao chép từ mã nguồn và chỉnh sửa ở đó, nhưng là cách duy nhất tôi tìm thấy. Dưới đây đang Backbone mặc định (1.0.0) và đánh dấu mã tùy chỉnh của tôi:
Backbone.Router.prototype.route = function(route, name, callback) {
if (!_.isRegExp(route)) route = this._routeToRegExp(route);
if (_.isFunction(name)) {
callback = name;
name = '';
}
if (!callback) callback = this[name];
// here my custom code
callback = _.wrap(callback, _.bind(function(cb) {
if (name == 'login' || sessionModel.authenticated()) {
_.bind(cb, this)();
} else {
this.navigate('login', {trigger: true});
}
}, this));
// finish my custom code
var router = this;
Backbone.history.route(route, function(fragment) {
var args = router._extractParameters(route, fragment);
callback && callback.apply(router, args);
router.trigger.apply(router, ['route:' + name].concat(args));
router.trigger('route', name, args);
Backbone.history.trigger('route', router, name, args);
});
return this;
};
Thông báo _.wrap
và _.bind
nên this
là một mà bạn mong đợi khi sử dụng router. Nếu không, tôi đã nhận được một lỗi "này là không xác định".
ethnagnawl và Alexey đều chính xác; _.wrap
là giải pháp phù hợp nhưng nếu bạn có một loạt các tuyến đường và viết chúng theo kiểu xương sống bình thường thì nó sẽ là một cơn đau.Tôi nhận ra bạn có thể làm điều này:
var Pages = {}
Pages.loginPage = function(){ ... }
Pages.mainPage = function(){ ... }
Thay vì xác định xử lý tuyến đường của bạn trực tiếp trong Router.extend
, tải chúng vào một đối tượng và sau đó làm điều này:
_.map(Pages,function(func,name){
Pages[name] = _.wrap(func,function(funky){
// Save original arguments
var args = Array.prototype.slice.call(arguments,1);
// Do stuff before the route
funky(args);
// Do stuff after the route
});
});
này cũng làm cho nó khá dễ dàng để kiểm tra tên hàm nếu bạn cần xử lý một tập hợp con của chúng một cách khác nhau hoặc một cái gì đó. Sau đó, bởi vì nó chỉ là một đối tượng, bạn có thể làm điều này:
var myRouter = Backbone.Router.extend({
routes: ... /* as usual */
}).extend(Pages);
Và bạn đã hoàn tất.
Một lợi thế tốt đẹp của việc này là nó không liên quan đến các nguyên mẫu Backbone, vì vậy ngay cả khi cập nhật phiên bản thay đổi một cái gì đó nó sẽ không cắn bạn.
sau khi thực hiện nhiều thao tác hơn. i đến một giải pháp mà tôi đã đưa ra dưới đây ...... Đây ur chức năng gốc ban đầu ...
route: function(route, name, callback) { if (!_.isRegExp(route)) route = this._routeToRegExp(route); if (_.isFunction(name)) { callback = name; name = ''; } if (!callback) callback = this[name]; var router = this; Backbone.history.route(route, function(fragment) { var args = router._extractParameters(route, fragment); callback && callback.apply(router, args); router.trigger.apply(router, ['route:' + name].concat(args)); router.trigger('route', name, args); Backbone.history.trigger('route', router, name, args); }); return this; }
Bây giờ nhìn vào mã này & thay đổi "lộ trình" chức năng để Backbone ban đầu của bạn .js ...
route: function(route, name, callback) {
if (!_.isRegExp(route)) route = this._routeToRegExp(route);
if (_.isFunction(name)) {
callback = name;
name = '';
}
if (!callback) callback = this[name];
var router = this;
Backbone.history.route(route, function(fragment) {
// takes matched route & fragment as like 'route1'
var args = router._extractParameters(route, fragment);
// extracts arguments if exists
// here yours self invoking function or other function starts....
(function(){
// do something
if (true) // condition satisfies then route to the given Route
{
callback && callback.apply(router, args);
}
else{
name='route2'; // change name of route
window.location.hash = 'route2';
callback= function(){
// optional callback if u want
}
callback && callback.apply(router, args); // route to ur custome Route
}
})();
});
return this;
}
----- Cảm ơn bạn -------- Love 2 write Dirty Codes! @xy ....
Đây là phiên bản JavaScript hoạt động với những gì tôi có;
var rp = Backbone.Router.prototype;
rp.routeWithoutEvents = rp.route;
rp.route = function(route, name, callback) {
if (!callback) callback = this[name];
this.routeWithoutEvents(route, name, function() {
this.before.apply(this);
callback.apply(this,arguments);
this.after.apply(this);
});
};
Nó dựa trên các giải pháp của Alexey Petrushin và Jonathan Tran.
Đây là một trong những đơn giản, trọng các Backbone.Router tự
(function() {
_.extend(Backbone.Router.prototype, Backbone.Events, {
route: function (route, name, callback) {
if (!_.isRegExp(route)) route = this._routeToRegExp(route);
if (!callback) callback = this[name];
Backbone.history.route(route, _.bind(function (fragment) {
var args = this._extractParameters(route, fragment);
if (this.before && _.isFunction(this.before)) {
this.before(fragment);
}
callback && callback.apply(this, args);
this.trigger.apply(this, ['route:' + name].concat(args));
if (this.after && _.isFunction(this.after)) {
this.after(fragment);
}
Backbone.history.trigger('route', this, name, args);
}, this));
return this;
}
});
}).call(this);
Tập trung vào các dòng
if (this.before && _.isFunction(this.before)) {
this.before(fragment);
}
VÀ
if (this.after && _.isFunction(this.after)) {
this.after(fragment);
}
Bạn có thể sửa đổi các dòng theo của bạn cần
Và đây là mã khách hàng sử dụng các lớp Backbone.Router mới
var appRouter = Backbone.Router.extend({
routes: {},
before: function(){
//your code here
return true;
}
});
Thực hiện tốt. Cảm ơn nhiều. – Trip
tôi không thể tìm thấy một cách dễ dàng để đánh chặn các sự kiện định tuyến trước khi xử lý tuyến đường được gọi.
Giải pháp của tôi là mở rộng thành phần Bộ định tuyến, thêm phương thức registerBeforeRouting và chỉnh sửa phương thức tuyến đường (tôi lấy nó từ Backbone 1.0 và nó hoạt động, YMMV với các phiên bản Backbone khác nhau).
Trước khi router được tạo ra:
var rp = Backbone.Router.prototype;
rp.registerBeforeRouting = function (callback) {
this._beforeRoutingCallback = callback;
};
rp.route = function (route, name, callback) {
if (!_.isRegExp(route)) route = this._routeToRegExp(route);
if (_.isFunction(name)) {
callback = name;
name = '';
}
if (!callback) callback = this[name];
var router = this;
Backbone.history.route(route, function(fragment) {
var args = router._extractParameters(route, fragment);
// Edit starts here
// This will trigger the callback previously set
if (typeof router._beforeRoutingCallback === 'function') {
router._beforeRoutingCallback();
}
// Edit stops here.
callback && callback.apply(router, args);
router.trigger.apply(router, ['route:' + name].concat(args));
router.trigger('route', name, args);
Backbone.history.trigger('route', router, name, args);
});
return this;
}
Sau đó, trong bộ định tuyến khởi tạo:
this.registerBeforeRouting(function() {
console.log("Hello world");
});
Tôi đã thử các cách tiếp cận nói trên, và họ bằng cách nào đó chỉ không làm việc cho tôi (có lẽ cho tôi thiếu hiểu biết sâu sắc về cả xương sống lẫn javascript nói chung). Tôi đã cố gắng thực hiện thủ thuật theo cách khác, nếu bất kỳ ai quan tâm đến bất kỳ ai:
Điều tôi thực sự làm chỉ đơn giản là kéo dài Chế độ xem và ghi đè hàm kết xuất chỉ một lần.
MyApp.BindedView = Backbone.View.extend({
_realRender : null,
initialize : function(){
//validating user is logged in:
if(Backbone.history.fragment != 'login' && !myUser.authenticated())
{
console.log('not authorized, redirecting');
var self = this;
this._realRender = this.render;
this.render = function(route,name,callback){
appRouter.navigate('login');
self.render = self._realRender;
}
return;
}
this.delegateEvents();
}
});
Phương pháp execute
đã được thêm vào để ghi đè cho mục đích này. Xem ví dụ này được trích xuất từ trang chủ backbonejs:
var Router = Backbone.Router.extend({
execute: function(callback, args, name) {
if (!loggedIn) {
goToLogin();
return false;
}
args.push(parseQueryString(args.pop()));
if (callback) callback.apply(this, args);
}
});
- 1. kích hoạt tuyến đường backbone.js mà không thay đổi url
- 2. Phương thức lớp hoạt động khác khi được gọi là phương thức thể hiện?
- 3. Thực hiện một chức năng trước khi thay đổi tuyến đường trong Backbone.js
- 4. định tuyến backbone.js khi truy vấn được chuyển đến tuyến đường chứa/
- 5. Phương thức nào được gọi khi một QGraphicsItem được chọn
- 6. Phương thức hủy của mô hình Backbone.js không kích hoạt thành công hoặc lỗi sự kiện
- 7. cách phương thức tìm nạp mô hình backbone.js hoạt động
- 8. Tham số tùy chọn tuyến đường Backbone.js
- 9. Làm gián đoạn cuộc gọi đường Backbone.js bằng Jasmine
- 10. Phương thức hoạt động nào được gọi trước?
- 11. Lịch sử Backbone.js 'trên sự kiện thay đổi tuyến đường'?
- 12. Phương thức CustomValidator ServerValidate không kích hoạt
- 13. Đồng bộ Backbone.js không kích hoạt bất kỳ sự kiện nào trên mô hình
- 14. Phương thức hoạt động gọi từ Fragment
- 15. Ghi đè phương thức trợ giúp tuyến đường
- 16. UIScrollView scrollRectToVisible: hoạt hình: có cách nào mà một phương thức có thể được gọi khi hoạt ảnh kết thúc
- 17. Cách gọi phương thức hoạt động từ một dịch vụ
- 18. Ngăn chặn thanh tác vụ kích hoạt các dạng không phương thức khi hộp thoại phương thức hoạt động
- 19. Router Backbone.js không kích hoạt trên trang init
- 20. Có an toàn khi gọi phương thức được đồng bộ từ một phương thức được đồng bộ khác không?
- 21. Khi nào thì phương thức getView() của ListView được gọi?
- 22. Nhận giá trị tham số null trong bộ điều khiển khi tuyến đường MVC kích hoạt
- 23. Backbone Router không kích hoạt đường
- 24. Ngăn chặn một phương thức được gọi trước một phương thức khác
- 25. Phương thức layoutSubviews được gọi là khi nào?
- 26. ném RuntimeException khi gọi phương thức chưa được khóa
- 27. Khi phương thức AppInitialize được gọi trong ASP.NET?
- 28. Chơi 2.0, nhận tuyến đường/url/Cuộc gọi hiện hoạt?
- 29. Gọi phương thức khi chuỗi kết thúc
- 30. Sử dụng Backbone.history để quay trở lại mà không kích hoạt chức năng tuyến đường
Điều này trông giống như một giải pháp vững chắc, nhưng tôi có một vấn đề, tôi không thể đọc coffeesript. Có cách nào bạn có thể dịch này vào javascript. Tôi đã thử trình biên dịch trực tuyến, nhưng điều đó làm cho mã thậm chí còn khó đọc hơn đối với tôi. –
Nó không hiệu quả với tôi, nhưng tôi đã tìm ra một giải pháp khác. –
@AmebaSpugnosa Liên kết với giải pháp? – kehers