我想要在分別在我的Backbone.js路由器中觸發路由之前和之後調用setup/teardown方法。有沒有人創建一個這樣做的優雅方式?Backbone.js - 在路由被觸發之前/之後的呼叫方法
回答
_.wrap不是一個解決方案,如果你有例如20條路線,你必須包裝所有。
但是你可以用元編程做這個
class Backbone.FlexRouter extends Backbone.Router
route: (route, name, handler) ->
super route, name, ->
@trigger "route:before"
handler()
@trigger "route:after"
UPD:我相信JS就應該是這樣的(但我沒有測試過)
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")
})
}
你考慮過_.wrap嗎?
這個插件做了什麼你要。它適用於0.5.3。我不確定它是否適用於0.9.1。
阿列克謝的答案是差不多吧,但也有缺少一些微妙的東西。
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
你的答案更精確,但它可能無法正常工作,因爲回調可能沒有提供。在這種情況下,路由方法默認查找名爲路由名稱的函數(請參閱我的答案中的代碼)。 –
@AmebaSpugnosa這一行處理,所以我不知道你的意思:'callback = @ [name] if!回調' –
如果您繼續使用Backbone.js源代碼,您將看到Router.route不僅僅準備了一個簡單的回調。在某些情況下,回調本身可以通過命名約定而不是通過引用傳遞來找到。這就是爲什麼你不能像你一樣包裝它。 –
我早些時候遇到過這個問題,我想我會分享我的解決方案,將「中間件」插入Backbone路由流。我們的目標是重新路由的用戶,這取決於一些條件不同的流,例如,特徵標誌,會話處理等。
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);
});
}
});
從那裏,你可以簡單地用protectedRoutes
哈希延長Backbone.ProtectedRouter
像這樣:
var router = Backbone.ProtectedRouter.extend({
protectedRoutes: {
'home': {
assertion: function() { return is_logged_in; },
method: 'renderLogin',
args: ['some_arg']
}
},
routes: {
'home': 'renderHome'
},
...
});
在這種情況下,如果做出請求的home
路線和is_logged_in
是false
,所述renderLogin
方法被調用,並通過'some_arg'
。流程結束後,renderLogin
將返回已解析的延遲,導致原始處理程序(renderHome
)被調用。
我希望這會有所幫助。我也非常樂於接受建議! :)
我最近碰到這個需求(檢查用戶是否通過驗證)。不幸的是Backbone不會給我們一個事前/事件後的事件,所以你需要覆蓋或擴展Router.route。因爲您必須從源代碼複製並在那裏編輯,所以感覺不太乾淨,但這是我找到的唯一方法。下面骨幹默認代碼(1.0.0),標誌着我的自定義代碼:
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;
};
通知_.wrap
和_.bind
所以this
是使用路由器時,你會期望之一。否則,我得到了「這是未定義的」錯誤。
ethnagnawl和Alexey都是正確的; _.wrap
是正確的解決方案,但是如果你有一堆路線並以正常的骨幹時尚寫入,這將是一個痛苦。我意識到,你可以這樣做:
var Pages = {}
Pages.loginPage = function(){ ... }
Pages.mainPage = function(){ ... }
,而不是直接在Router.extend
定義你的路由處理程序,它們加載到一個對象,然後做到這一點:
_.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
});
});
這也使得它很容易檢查函數名稱,如果你需要對待它們的一個子集或不同的東西。然後,因爲它只是一個對象,所以你可以這樣做:
var myRouter = Backbone.Router.extend({
routes: ... /* as usual */
}).extend(Pages);
然後你就完成了。
這樣做的好處之一是它不涉及Backbone原型,所以即使版本更新改變了它也不會咬你。
做了很多操作之後。我來,我有如下的解決方案...... 這裏烏爾根原...功能
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; }
現在看這個代碼&改變「路線」功能,原來的骨幹.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;
}
-----謝謝-------- 愛情2寫入髒代碼! @xy ....
這是一個JavaScript版本,與我的工作;
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);
});
};
它是基於Alexey Petrushin和Jonathan Tran的解決方案。
這裏是簡單的一個,覆蓋Backbone.Router本身
(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);
專注於線
if (this.before && _.isFunction(this.before)) {
this.before(fragment);
}
和
if (this.after && _.isFunction(this.after)) {
this.after(fragment);
}
您可以根據修改的行需要
這裏是使用新Backbone.Router類
var appRouter = Backbone.Router.extend({
routes: {},
before: function(){
//your code here
return true;
}
});
幹得好。非常感謝你。 – Trip
我無法找到一個簡單的方法來攔截路由事件的路由處理程序被調用之前的客戶端代碼。
我的解決方案是擴展路由器組件,添加一個registerBeforeRouting方法並編輯路由方法(我從Backbone 1.0開始使用它,它的工作原理是YMMV和不同的Backbone版本)。
路由器創建前:
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;
}
然後,路由器初始化期間:
this.registerBeforeRouting(function() {
console.log("Hello world");
});
我嘗試了上述的方法,並在某種程度上只是不爲我工作(可能是我的沒有深入瞭解任何骨幹,也沒有一般的JavaScript)。 我確實設法以其他方式來做這個伎倆,如果這對任何人都有興趣:
我最終做的只是簡單地擴展視圖並重寫渲染函數一次。加入
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();
}
});
execute
的方法被覆蓋用於此目的。看到這個例子從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. Mockito在一組其他呼叫之前/之後驗證呼叫
- 2. 在呼叫路由控制器之前進行身份驗證
- 3. Backbone.js路由沒有被觸發
- 4. setLast方法在actionListener方法之前被觸發
- 5. 使用Marionette路由方法之前/之後AppRouter
- 6. Backbone.js路由沒有觸發
- 7. 在調度的UILocalNotification之前調用的方法被觸發?
- 8. 設置視圖之前或之後呼叫超級?所有的
- 9. 呼叫使用動作呼叫之前其他方法asp.net MVC 2
- 10. Backbone.js路由方法沒有被調用
- 11. 呼叫者在客戶端回答之前斷開呼叫
- 12. Twilio呼叫路由
- 13. 呼叫路由-n在cgi
- 14. 在路由呼叫開始之前丟棄一個數據包:openSIPS
- 15. 在AJAX呼叫之後,下一個AJAX呼叫不起作用
- 16. 等待所有文件在觸發下一個路由之前被消耗
- 17. 在改變Backbone.js中的路由之前執行一個函數
- 18. Flexigrid在呼叫之後不會填充。
- 19. 之前被觸發的事件(不是之後!)DOM元素被滾動到javascript
- 20. 流星 - 使用UI路由器加載狀態之前的呼叫功能
- 21. 谷歌電子表格:在觸發器(事件)開啓之前攔截呼叫
- 22. 在顯示本地通知之前是否可以觸發api呼叫?
- 23. 茉莉花在呼叫之後解決承諾,但在此之前預計
- 24. 呼叫show.bs.modal事件父事件之前
- 25. 呼叫JS功能之前重定向
- 26. 遞歸 - 三角形在循環之前發出呼叫
- 27. 觸發backbone.js路由而不更改url
- 28. NSTimer在觸發之前觸發
- 29. 在oracle中觸發之前和之後的區別
- 30. 角路由呼叫跨域
這看起來像一個堅實的解決方案,但我有一個問題,我不能讀取咖啡餡餅。有什麼辦法可以把它轉換成javascript。我已經嘗試過在線編譯器,但是這使得我的代碼更加難以理解。 –
它沒有爲我工作,但我找到了另一種解決方案。 –
@AmebaSpugnosa鏈接到解決方案? – kehers