在鼠标单击事件上切换 class
Toggle class on mouse click event
我有一个 Backbone.View
可以呈现一个集合并在鼠标单击时对其进行过滤。我需要将 class active
添加到我单击的按钮,但问题是按钮是此视图的一部分,每当我尝试 addClass
或 toggleClass
时只需使用默认 class 再次呈现。这是我的观点:
var ResumeList = Backbone.View.extend({
events: {
'click #active': 'showActive',
'click #passed': 'showPassed'
},
initialize: function () {
this.collection = new ResumeCollection();
},
render: function (filtered) {
var self = this;
var data;
if (!filtered) {
data = this.collection.toArray();
} else {
data = filtered.toArray();
}
this.$el.html(this.template({ collection: this.collection.toJSON() });
_.each(data, function (cv) {
self.$el.append((new ResumeView({model: cv})).render().$el);
});
return this;
},
showActive: function () {
this.$('#active').toggleClass('active');
// a function that returns a new filtered collection
var filtered = this.collection.filterActive();
this.render(filtered);
}
});
但是正如我已经说过的,我需要的 class 只是暂时切换或添加,然后再次呈现视图并将其设置为默认值 class。有什么办法可以解决这个问题吗?
我已经编辑了代码片段,你可以试试这个吗?
var ResumeList = Backbone.View.extend({
events: {
'click #active': 'filterActive',
'click #passed': 'showPassed'
},
toggleElement: undefined,
initialize: function () {
this.collection = new ResumeCollection();
},
render: function (filtered) {
var self = this;
var data;
if (!filtered) {
data = this.collection.toArray();
} else {
data = filtered.toArray();
}
this.$el.html(this.template({ collection: this.collection.toJSON() });
_.each(data, function (cv) {
self.$el.append((new ResumeView({model: cv})).render().$el);
});
return this;
},
filterActive: function (evt) {
this.toggleElement = this.$el.find(evt.currentTarget);
// a function that returns a new filtered collection
var filtered = this.collection.filterActive();
this.render(filtered);
this.toggleActive();
},
toggleActive: function() {
if(this.toggleElement.is(':checked')) {
this.$el.find('#active').addClass('active');
} else {
this.$el.find('#active').removeClass('active');
}
}
});
请注意:我使用了复选框元素而不是按钮。
我简化了渲染并添加了一些优化。
由于我们没有您的模板,我将其更改为启用优化:
<button id="active" type="button">Active</button>
<button id="passed" type="button">Passed</button>
<div class="list"></div>
那么您的列表视图可能是这样的:
var ResumeList = Backbone.View.extend({
events: {
'click #active': 'showActive',
'click #passed': 'showPassed'
},
initialize: function() {
this.childViews = [];
this.collection = new ResumeCollection();
},
render: function() {
this.$el.html(this.template());
// cache the jQuery element once
this.elem = {
$list: this.$('.list'),
$active: this.$('#active'),
$passed: this.$('#passed')
};
this.renderList(); // default list rendering
return this;
},
renderList: function(collection) {
this.elem.$list.empty();
this.removeChildren();
collection = collection || this.collection.models;
// Underscore's 'each' has a argument for the context.
_.each(collection, this.renderItem, this);
},
renderItem: function(model) {
var view = new ResumeView({ model: model });
this.childViews.push(view);
this.elem.$list.append(view.render().el);
},
showActive: function() {
this.elem.$active.toggleClass('active');
var filtered = this.collection.filterActive();
this.renderList(filtered);
},
/**
* Gracefully call remove for each child view.
* This is to avoid memory leaks with listeners.
*/
removeChildren: function() {
var view;
while ((view = this.childViews.pop())) {
view.remove();
}
},
});
附加信息:
- Managing Views and Memory Leaks
- Underscore's
each
(注意第三个参数)
- 尽量避免 callback hell,使回调可重用(如
renderItem
)
我有一个 Backbone.View
可以呈现一个集合并在鼠标单击时对其进行过滤。我需要将 class active
添加到我单击的按钮,但问题是按钮是此视图的一部分,每当我尝试 addClass
或 toggleClass
时只需使用默认 class 再次呈现。这是我的观点:
var ResumeList = Backbone.View.extend({
events: {
'click #active': 'showActive',
'click #passed': 'showPassed'
},
initialize: function () {
this.collection = new ResumeCollection();
},
render: function (filtered) {
var self = this;
var data;
if (!filtered) {
data = this.collection.toArray();
} else {
data = filtered.toArray();
}
this.$el.html(this.template({ collection: this.collection.toJSON() });
_.each(data, function (cv) {
self.$el.append((new ResumeView({model: cv})).render().$el);
});
return this;
},
showActive: function () {
this.$('#active').toggleClass('active');
// a function that returns a new filtered collection
var filtered = this.collection.filterActive();
this.render(filtered);
}
});
但是正如我已经说过的,我需要的 class 只是暂时切换或添加,然后再次呈现视图并将其设置为默认值 class。有什么办法可以解决这个问题吗?
我已经编辑了代码片段,你可以试试这个吗?
var ResumeList = Backbone.View.extend({
events: {
'click #active': 'filterActive',
'click #passed': 'showPassed'
},
toggleElement: undefined,
initialize: function () {
this.collection = new ResumeCollection();
},
render: function (filtered) {
var self = this;
var data;
if (!filtered) {
data = this.collection.toArray();
} else {
data = filtered.toArray();
}
this.$el.html(this.template({ collection: this.collection.toJSON() });
_.each(data, function (cv) {
self.$el.append((new ResumeView({model: cv})).render().$el);
});
return this;
},
filterActive: function (evt) {
this.toggleElement = this.$el.find(evt.currentTarget);
// a function that returns a new filtered collection
var filtered = this.collection.filterActive();
this.render(filtered);
this.toggleActive();
},
toggleActive: function() {
if(this.toggleElement.is(':checked')) {
this.$el.find('#active').addClass('active');
} else {
this.$el.find('#active').removeClass('active');
}
}
});
请注意:我使用了复选框元素而不是按钮。
我简化了渲染并添加了一些优化。
由于我们没有您的模板,我将其更改为启用优化:
<button id="active" type="button">Active</button>
<button id="passed" type="button">Passed</button>
<div class="list"></div>
那么您的列表视图可能是这样的:
var ResumeList = Backbone.View.extend({
events: {
'click #active': 'showActive',
'click #passed': 'showPassed'
},
initialize: function() {
this.childViews = [];
this.collection = new ResumeCollection();
},
render: function() {
this.$el.html(this.template());
// cache the jQuery element once
this.elem = {
$list: this.$('.list'),
$active: this.$('#active'),
$passed: this.$('#passed')
};
this.renderList(); // default list rendering
return this;
},
renderList: function(collection) {
this.elem.$list.empty();
this.removeChildren();
collection = collection || this.collection.models;
// Underscore's 'each' has a argument for the context.
_.each(collection, this.renderItem, this);
},
renderItem: function(model) {
var view = new ResumeView({ model: model });
this.childViews.push(view);
this.elem.$list.append(view.render().el);
},
showActive: function() {
this.elem.$active.toggleClass('active');
var filtered = this.collection.filterActive();
this.renderList(filtered);
},
/**
* Gracefully call remove for each child view.
* This is to avoid memory leaks with listeners.
*/
removeChildren: function() {
var view;
while ((view = this.childViews.pop())) {
view.remove();
}
},
});
附加信息:
- Managing Views and Memory Leaks
- Underscore's
each
(注意第三个参数) - 尽量避免 callback hell,使回调可重用(如
renderItem
)