backbone.js事件在重新渲染后没有触发
[编辑:我通过调用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);
}
}
});
您清空#login div。作为jQuery的医生说:
为了避免内存泄漏,jQuery的去除 元素本身之前将其他结构,比如从子元素数据 和事件处理程序。
因此,您正在有效地从您的意见中删除事件。我更喜欢使用detach,因为它保留了事件。 http://api.jquery.com/detach/
你可以在你的视图中实现一个显示/隐藏来处理这个问题。
你救了我救了几个小时! – tmimicus
我正面临同样的问题。我现在解决它的方式是使用new MyView()
完全重新实例化View对象,这可以确保事件被反弹。
希望有帮助吗?
我找到了一个解决方案,因为我遇到了同样的问题,实际上detach()不是解决方案,因为它会为您带回旧的DOM元素,这是没有用的。
这是你需要的,如果你用你的事件将不会触发的.html()方法来做
render: function(){ this.$el.empty(); ...... this.$el.appendTo($DOM); }
什么。 您需要使用appendTo()将新创建的HTML附加到DOM。
顺便说一句,这只发生在我身上,如果您使用tagName和className来动态构建您的视图。
当使用$(el).empty()
它删除在所选择的元件的所有子元素,并删除所有的事件(和数据),这些束缚于任何(子)单元选定元件(el
)的内部。
为了保持势必的子元素的事件,但还是删除子元素,使用:的
$(el).children().detach();
代替$(.el).empty();
这将使你的观点与事件成功地重新解析仍然约束和工作。
请参阅以下内容以供进一步参考:http://stackoverflow.com/a/12029250/2728686和http://www.jquerybyexample.net/2012/05/empty-vs-remove-vs-detach-jquery.html – AmpT
您需要提供更多信息以了解正在发生的事情以及原因。你能发布更多的视图代码和你的路由器代码吗? –
这里是我的路由器和受影响的视图:主要= 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
我无法添加视图 - 对于此编辑器来说太大了,无法接受。 LoginView具有事件子句。 – Greg