【发布时间】:2016-11-03 12:45:32
【问题描述】:
过去我读过很多关于可组合性优于继承的文章,我完全认同这个概念,并在我的代码中大量使用了这一原则。
但是,我在日常工作中遇到了一些问题,继承往往会渗透到视图中,并且我很难看到如何实现更可组合的东西(我在日常使用 Backbone 的事实没有帮助到日常工作)。这些往往是我想使用现有 Backbone 视图的所有功能,同时在顶部添加一些额外功能的时候。
以这个假设的例子为例,我们有一个电子商务类型的页面,其中包含多个 Product 视图,每个视图代表特定产品的可购物选项集合:
var ProductView = (function(Backbone, JST) {
'use strict';
return Backbone.View.extend({
className: 'product',
template: JST['application/templates/product']
initialize: function(options) {
this.options = options || {};
this.collection.fetch();
this.listenTo(this.collection, 'loaded', this.render);
},
render: function() {
this.$el.html(
this.template(this.collection)
);
return this;
},
}, {
create: function(el) {
var endpoint = '/api/options/' + el.getAttribute('data-basket-id') + '/' + el.getAttribute('data-product-id');
new ProductView({
el: el,
collection: new ProductCollection(null, { url: endpoint })
});
}
});
})(Backbone, JST);
假设我们想要展示一些需要使用确认框提示访问者的产品(假设出于保险原因,该特定产品必须以保险形式出售,因此我们需要在用户添加它时提示他们到他们的篮子里):
var InsuranceProductView = (function (_, ProductView) {
'use strict';
return ProductView.extend({
consentTemplate: JST['application/templates/product/insurance_consent'],
initialize: function (options) {
this.listenTo(this.model, 'change:selected', function (model) {
if (!model.get('selected')) {
this.removeMessage()
}
});
ProductView.prototype.initialize.apply(this, arguments);
},
events: function () {
return _.extend({}, ProductView.prototype.events, {
'change input[type=radio]': function () {
this.el.parentElement.appendChild(this.consentTemplate());
},
'change .insurance__accept': function () {
ProductView.prototype.onChange.apply(this);
},
});
},
removeMessage: function () {
var message = this.el.parentElement.querySelector('.insurance__consent');
message.parentNode.removeChild(message);
},
});
})(_, ProductView);
有没有更可组合的方式来写这个?或者这是一种通过继承中断是正确的情况?
【问题讨论】:
标签: javascript inheritance backbone.js composition