Sub Class a Backbone.View. Подкласс и сохранение событий.
У меня есть общий подкласс Backbone.View
, который имеет прослушиватель событий close
.
var GenericView = Backbone.View.extend({
events : {
"click .close" : "close"
},
close : function () {
console.log("closing view");
}
});
Я хочу подклассифицировать этот общий класс и добавить некоторые новые события. Однако ниже будет перезаписываться объект событий super classes (выше). Например.
var ImplementedView = new GenericView({
// setting this will stop 'close' in Super Class from triggering
events : {
"click .submit" : "submit"
}
});
Как мне создать подкласс, в данном случае ImplementedView
и сохранить события?
Я нашел один способ достичь этого, расширив объект события, когда построен дочерний класс. Однако мне нужно перезапустить this.delegateEvents()
, который, как я предполагаю, не очень хорош. Может ли кто-нибудь прокомментировать это?
var ImplementedView = new GenericView({
initialize : function (options) {
_.extend(this.events, {
"click .submit" : "submit"
});
// re-attach events
this.delegateEvents();
}
});
Ответы
Ответ 1
@Nupul в точности соответствует: вы не подклассифицируете свой GenericView
.
На самом деле подклассификация здесь не является правильным словом, поскольку JavaScript не выполняет классического наследования.
Итак, давайте сначала попытаемся понять, что происходит здесь:
var GenericView = Backbone.View.extend( propertiesObj, classPropertiesObj )
Backbone.View
- это функция-конструктор, которая при вызове с ключевым словом new
создает для вас новый объект.
Поскольку это JS, все функции являются действительно объектами функции, поэтому Backbone.View.extend
- это просто функция, зависающая от Backbone.View
, которая выполняет несколько действий:
- Он устанавливает цепочку прототипов, поэтому вы можете обращаться к свойствам и функциям вызова, определенным в классе "base"
- Он создает и возвращает новую конструкторскую функцию, которую вы можете вызвать (которая здесь была бы
GenericView
) для создания объектов вашего класса наследования
- Он копирует себя как функцию, зависающую от возвращаемой функции-конструктора, чтобы вы могли наследовать.
Таким образом, правильный способ настройки цепи protoype вы хотите:
var ImplementedView = GenericView.extend({
// implementation goes here
});
и NOT:
var ImplementedView = new GenericView({//stuff});
потому что это просто создает новый экземпляр GenericView.
Теперь у вас все еще есть проблема, потому что когда вы делаете что-то вроде:
var impl_view = new ImplementedView;
impl_view.events; // This isn't merged with the events you created
// for the GenericView
В этот момент есть разные способы получить желаемый результат, вот тот, который использует delegateEvents
вроде того, как вы это делали. Кстати, использование этого неплохо.
var GenericView = Backbone.View.extend({
genericEvents: { 'click .close': 'close' },
close: function() { console.log('closing view...'); }
});
var ImplView = GenericView.extend({
events: { 'click .submit': 'submit' },
initialize: function(options) {
// done like this so that genericEvents don't overwrite any events
// we've defined here (in case they share the same key)
this.events = _.extend({}, this.genericEvents, this.events);
this.delegateEvents()
}
});
Ответ 2
Другой вариант - иметь BaseView, который переопределяет реализацию Extend. Например:
var BaseView = Backbone.View.extend({
//base view functionality if needed
});
BaseView.extend = function(child){
var view = Backbone.View.extend.apply(this, arguments);
view.prototype.events = _.extend({}, this.prototype.events, child.events);
return view;
};
Это автоматически расширит все ваши события для всего, что наследуется от BaseView.
Ответ 3
Мне нравится решение г-на Бритва, но для чего-то менее навязчивого:
var ChildView = ParentView.extend({
events : _.extend({
"change input": "handleInputChange"
}, ParentView.prototype.events)
});
Изменить. Да, вы должны сделать это в каждом дочернем классе, но это полезно, когда нужны только несколько детей или когда вы не контролируете родительский "класс".
Ответ 4
Вот решение, которое хорошо сработало для меня. Вы можете использовать объект events как в родительском, так и в подклассе, без расширения в нем каждого подкласса. Просто добавьте его один раз в родительский класс:
APP.Views.GenericWizard = Backbone.View.extend({
events: {
'click .btn-prev' : function(){}
},
initialize: function() {
_(this.events).extend(APP.Views.GenericWizard.prototype.events);
}
});
APP.Views.RegisterWizard = APP.Views.GenericWizard.extend({
events: {
'blur #username' : function(){}
},
});
var registerWizard = new APP.Views.RegisterWizard();
console.log(registerWizard.events);
// Object {blur #username: function, click .btn-prev: function}
Ответ 5
Вы можете найти это полезным: http://kalimotxocoding.blogspot.com/2011/03/playing-with-backbonejs-views.html
Секунды, о которых я упоминал о _.extend(...)
и о том, что у вас в настоящее время есть...