2011-09-08 73 views
24

[編輯:我通過調用delegateEvents()解決了前面的問題,但不應該。重新張貼瓦特/更多信息。]backbone.js事件在重新渲染後沒有觸發

我有一個視圖,當呈現有一個登錄按鈕,並附加一個點擊事件。首先渲染所有作品:單擊按鈕,一旦成功調用ajax,登錄提示消失並顯示歡迎視圖(LoggedInView)。但是,如果稍後導航回到此視圖(#foo),UI將呈現,但事件關聯不會通過調用delegateEents()手動強制解決問題。

發生了什麼,我的事件沒有重新聯繫自己?

LoginView = Backbone.View.extend({ 
    template: _.template($("#loginTemplate").html()), 
    initialize: function(stuff,router) { 
     _.bindAll(this,'render','rc','gotProfile'); 
     this.model.bind("rc",this.rc) 
     this.router = router; 
    }, 
    events: { 
     'click .loginButton': 'login' 
    }, 
    render: function() { 
     $(this.el).html(this.template(this.model.toJSON())); 
     $(this.el).find(".actionButton").button(); // Button 
//  this.delegateEvents(this.events); // NEEDED! Re-wire events on re-render 
     return this; 
    }, 
    rc: function(code) { 
     switch(code) { 
      case errCodes.USER_NOT_FOUND: this.notFound(); break; 
      case errCodes.OK:    this.loginOk(); break; 
      default:       this.otherErr(); break; 
     } 
    }, 
    login: function() { 
     clearErrors($('[rel="req"]')); 
     var okReq = validate($('#login [rel="req"]'), validateReq); 
     var okEmail = validate([$('#uid')], validateEmail); 
     if(okReq && okEmail) { 
      this.model.set({'uid':$('#uid').val().trim(),  'pwd':$('#pwd').val().trim()}); 
      this.model.fetch(); 
     } 
    }, 
    notFound: function() { 
     validate([$('#uid'),$('#pwd')], function(){return[false,"Invalid user/password"]}); 
    }, 
    otherErr: function() { 
     validate([$('#uid'),$('#pwd')], function(){return[false,"Please contact support for help logging in."]}); 
    }, 
    loginOk: function() { 
     this.profile = new Profile({uid:this.model.get('uid'),token:this.model.get('key')}); 
     this.profile.bind("rc",this.gotProfile) 
     this.profile.fetch(); 
    }, 
    gotProfile: function() { 
     this.router.navigate('/',true); 
    } 
}); 

LoggedInView = Backbone.View.extend({ 
    template: _.template($("#loggedInTemplate").html()), 
    uList: new ProfileList(), 
    initialize: function() { 
     _.bindAll(this,'render','renderUserList','renderUser'); 
     this.model.bind('show', this.render); 
     this.uList.bind('rc', this.render); 
    }, 
    events: { 
     'click #ufa': 'getUsersForHouse' 
    }, 
    render: function() { 
     $(this.el).html(this.template(this.model.toJSON())); 
     this.renderUserList(); 
//  this.delegateEvents(this.events); // NEEDED! Re-wire events on re-render 
     return this; 
    }, 
    renderUserList: function() { 
     $(this.el).find('ul').empty(); 
     this.uList.each(this.renderUser); 
    }, 
    renderUser: function(aUser) { 
     $(this.el).find('#userList').append("<li>"+aUser.get('person').firstName+"</li>"); 
    }, 
    getUsersForHouse: function() { 
     this.uList.fetch(this.model.get('token'),"house"); 
    } 
}); 

Main = Backbone.Router.extend({ 
    routes: { 
     'foo': 'foo', 
     '*all': 'home' 
    }, 
    initialize: function() { 
     this.token = new Token(); 
     this.loginView = new LoginView({model:this.token},this); 
    }, 
    foo: function(){ // naving here looses click event on login button 
     $('#login').empty(); 
     $("#login").append(this.loginView.render().el); 
    }, 
    home: function() { 
     $('#login').empty(); 
     if(this.loginView.profile == null) 
      $("#login").append(this.loginView.render().el); 
     else { 
      this.loggedInView = new LoggedInView({model:this.loginView.profile}); 
      $("#login").append(this.loggedInView.render().el); 
     } 
    } 
}); 
+0

您需要提供更多信息以瞭解正在發生的事情以及原因。你能發佈更多的視圖代碼和你的路由器代碼嗎? –

+0

這裏是我的路由器和受影響的視圖:主要= Backbone.Router.extend({ \t路線:{ \t \t '': '家', \t \t 'OK': '的loggedIn' \t}, \t初始化:函數(){ \t \t this.token =新令牌(); \t \t this.loginView =新LoginView({模型:this.token},這一點); \t}, \t家:功能(){ \t \t $('#login')。empty(); \t \t $(「#login」)。append(this.loginView.render()。el); \t}, \t的loggedIn:函數(){ \t \t this.loggedInView =新LoggedInView({模型:this.loginView.profile}); \t \t $('#login')。empty(); \t \t $(「#login」)。append(this.loggedInView.render()。el); \t} }); – Greg

+0

我無法添加視圖 - 對於此編輯器來說太大了,無法接受。 LoginView具有事件子句。 – Greg

回答

18

您清空#login div。作爲jQuery的醫生說:

爲了避免內存泄漏,jQuery的去除 元素本身之前將其他結構,比如從子元素數據 和事件處理程序。

因此,您正在有效地從您的意見中刪除事件。我更喜歡使用detach,因爲它保留了事件。 http://api.jquery.com/detach/

你可以在你的視圖中實現一個顯示/隱藏來處理這個問題。

+1

你救了我救了幾個小時! – tmimicus

1

我正面臨同樣的問題。我現在解決它的方式是使用new MyView()完全重新實例化View對象,這可以確保事件被反彈。

希望有幫助嗎?

2

我找到了一個解決方案,因爲我遇到了同樣的問題,實際上detach()不是解決方案,因爲它會爲您帶回舊的DOM元素,這是沒有用的。

這是你需要的,如果你用你的事件將不會觸發的.html()方法來做

render: function(){ this.$el.empty(); ...... this.$el.appendTo($DOM); } 

什麼。 您需要使用appendTo()將新創建的HTML附加到DOM。

順便說一句,這隻發生在我身上,如果您使用tagName和className來動態構建您的視圖。

1

當使用$(el).empty()它刪除在所選擇的元件的所有子元素,並刪除所有事件(和數據),這些束縛於任何(子)單元選定元件(el)的內部。

爲了保持勢必子元素的事件,但還是刪除子元素,使用:的

$(el).children().detach();代替$(.el).empty();

這將使你的觀點與事件成功地重新解析仍然約束和工作。

+0

請參閱以下內容以供進一步參考:http://stackoverflow.com/a/12029250/2728686和http://www.jquerybyexample.net/2012/05/empty-vs-remove-vs-detach-jquery.html – AmpT

相關問題