답변:
한 가지 방법은 다음과 같습니다.
var ChildView = ParentView.extend({
events: function(){
return _.extend({},ParentView.prototype.events,{
'click' : 'onclickChild'
});
}
});
또 다른 것 :
var ParentView = Backbone.View.extend({
originalEvents: {
'click': 'onclick'
},
//Override this event hash in
//a child view
additionalEvents: {
},
events : function() {
return _.extend({},this.originalEvents,this.additionalEvents);
}
});
var ChildView = ParentView.extend({
additionalEvents: {
'click' : ' onclickChild'
}
});
이벤트가 기능인지 객체인지 확인하려면
var ChildView = ParentView.extend({
events: function(){
var parentEvents = ParentView.prototype.events;
if(_.isFunction(parentEvents)){
parentEvents = parentEvents();
}
return _.extend({},parentEvents,{
'click' : 'onclickChild'
});
}
});
parentEvents = _.result(ParentView.prototype, 'events');
'수동으로' events
함수 인지 확인 하는 대신 사용할 수 있어야 합니다.
_.result
내가 전에 알아 차리지 못했던 밑줄 유틸리티 함수를 언급 한 +1 . 관심이있는 사람을 위해 다음은이 테마에 대한 다양한 변형이있는 jsfiddle입니다. jsfiddle
this
인스턴스 이름으로 부모 클래스를 호출하는 것과 비교하는 것입니다. 이것에 대해 대단히 감사합니다.
soldier.moth 대답은 좋은 것입니다. 더 단순화하면 다음을 수행 할 수 있습니다.
var ChildView = ParentView.extend({
initialize: function(){
_.extend(this.events, ParentView.prototype.events);
}
});
그런 다음 일반적인 방법으로 두 클래스에서 이벤트를 정의하십시오.
this.events
및 ParentView.prototype.events
모두 동일한 이벤트 핸들러를 정의 할 경우, 그렇지 않으면 부모의 핸들러는 자녀의 우선합니다.
{},ParentView.prototype.events,this.events
delegateEvents
이벤트를 바인딩하기 위해 생성자에서 호출됩니다. 에서 확장 할 때 왜 initialize
너무 늦지 않았습니까?
initialize
으로 몇 가지 경우 (그런 다음 해당 기능의 계층 관리도 처리해야 함)를 작성해야합니다. 이벤트 개체를 병합합니다. events
병합 자체 를 유지하기 위해 나에게 더 깨끗한 것 같습니다 . 그 존재는 내가이 방법을 생각하지 않았을, 그것은 : 다른 방식으로 사물을보기로 강제하는 것이 좋다 말했다
계층 구조의 이벤트 상속을 처리하는 Backbone.View에서 특수 기본 생성자를 만드는 것이 더 쉽지 않을 것입니다.
BaseView = Backbone.View.extend {
# your prototype defaults
},
{
# redefine the 'extend' function as decorated function of Backbone.View
extend: (protoProps, staticProps) ->
parent = this
# we have access to the parent constructor as 'this' so we don't need
# to mess around with the instance context when dealing with solutions
# where the constructor has already been created - we won't need to
# make calls with the likes of the following:
# this.constructor.__super__.events
inheritedEvents = _.extend {},
(parent.prototype.events ?= {}),
(protoProps.events ?= {})
protoProps.events = inheritedEvents
view = Backbone.View.extend.apply parent, arguments
return view
}
이를 통해 재정의 된 확장 함수를 사용하여 새 '하위 클래스'(자식 생성자)를 만들 때마다 계층 구조 아래로 이벤트 해시를 줄이 (병합) 할 수 있습니다.
# AppView is a child constructor created by the redefined extend function
# found in BaseView.extend.
AppView = BaseView.extend {
events: {
'click #app-main': 'clickAppMain'
}
}
# SectionView, in turn inherits from AppView, and will have a reduced/merged
# events hash. AppView.prototype.events = {'click #app-main': ...., 'click #section-main': ... }
SectionView = AppView.extend {
events: {
'click #section-main': 'clickSectionMain'
}
}
# instantiated views still keep the prototype chain, nothing has changed
# sectionView instanceof SectionView => true
# sectionView instanceof AppView => true
# sectionView instanceof BaseView => true
# sectionView instanceof Backbone.View => also true, redefining 'extend' does not break the prototype chain.
sectionView = new SectionView {
el: ....
model: ....
}
확장 기능을 재정의하는 BaseView라는 특수 뷰를 생성함으로써 부모 뷰의 선언 된 이벤트를 상속하려는 하위 뷰 (예 : AppView, SectionView)를 BaseView 또는 그 파생물 중 하나에서 확장하여 간단하게 수행 할 수 있습니다.
대부분의 경우 부모 생성자를 명시 적으로 참조해야하는 서브 뷰에서 이벤트 함수를 프로그래밍 방식으로 정의 할 필요가 없습니다.
이것은 또한 작동합니다.
class ParentView extends Backbone.View
events: ->
'foo' : 'doSomething'
class ChildView extends ParentView
events: ->
_.extend({}, _.result(_super::, 'events') || {},
'bar' : 'doOtherThing')
스트레이트 super
를 사용 하는 것은 나를 위해 작동하지 않았으며 수동으로 ParentView
또는 상속 된 클래스를 지정했습니다 .
_super
모든 coffeescript 내에서 사용할 수 있는 var 에 대한 액세스Class … extends …
// ModalView.js
var ModalView = Backbone.View.extend({
events: {
'click .close-button': 'closeButtonClicked'
},
closeButtonClicked: function() { /* Whatever */ }
// Other stuff that the modal does
});
ModalView.extend = function(child) {
var view = Backbone.View.extend.apply(this, arguments);
view.prototype.events = _.extend({}, this.prototype.events, child.events);
return view;
};
// MessageModalView.js
var MessageModalView = ModalView.extend({
events: {
'click .share': 'shareButtonClicked'
},
shareButtonClicked: function() { /* Whatever */ }
});
// ChatModalView.js
var ChatModalView = ModalView.extend({
events: {
'click .send-button': 'sendButtonClicked'
},
sendButtonClicked: function() { /* Whatever */ }
});
Backbone 버전 1.2.3의 경우 __super__
잘 작동하며 연결될 수도 있습니다. 예 :
// A_View.js
var a_view = B_View.extend({
// ...
events: function(){
return _.extend({}, a_view.__super__.events.call(this), { // Function - call it
"click .a_foo": "a_bar",
});
}
// ...
});
// B_View.js
var b_view = C_View.extend({
// ...
events: function(){
return _.extend({}, b_view.__super__.events, { // Object refence
"click .b_foo": "b_bar",
});
}
// ...
});
// C_View.js
var c_view = Backbone.View.extend({
// ...
events: {
"click .c_foo": "c_bar",
}
// ...
});
... A_View.js
결과는 다음과 같습니다.
events: {
"click .a_foo": "a_bar",
"click .b_foo": "b_bar",
"click .c_foo": "c_bar",
}
이 기사 에서 더 흥미로운 해결책을 찾았습니다.
백본의 사용 super 와 ECMAScript의 hasOwnProperty를 사용합니다. 두 번째 진보적 사례는 매력처럼 작동합니다. 다음은 약간의 코드입니다.
var ModalView = Backbone.View.extend({
constructor: function() {
var prototype = this.constructor.prototype;
this.events = {};
this.defaultOptions = {};
this.className = "";
while (prototype) {
if (prototype.hasOwnProperty("events")) {
_.defaults(this.events, prototype.events);
}
if (prototype.hasOwnProperty("defaultOptions")) {
_.defaults(this.defaultOptions, prototype.defaultOptions);
}
if (prototype.hasOwnProperty("className")) {
this.className += " " + prototype.className;
}
prototype = prototype.constructor.__super__;
}
Backbone.View.apply(this, arguments);
},
...
});
당신은 또한 그것을 할 수 있습니다 ui 및 속성에 .
이 예제는 함수에 의해 설정된 속성을 처리하지 않지만이 경우 기사 작성자가 솔루션을 제공합니다.
이 작업을 부모 클래스에서 전적으로 수행하고 자식 클래스에서 함수 기반 이벤트 해시를 지원하여 자식이 상속에 무관심 할 수 있도록하려면 (자식이 MyView.prototype.initialize
재정의하는 경우 자식이 호출 해야 함 initialize
) :
var MyView = Backbone.View.extend({
events: { /* ... */ },
initialize: function(settings)
{
var origChildEvents = this.events;
this.events = function() {
var childEvents = origChildEvents;
if(_.isFunction(childEvents))
childEvents = childEvents.call(this);
return _.extend({}, MyView.prototype.events, childEvents);
};
}
});
에 ParentView
이벤트가 객체로 정의되어 있고 이벤트를 동적으로 정의 할 필요가없는 ChildView
경우 함수를 제거하고 _.extend
직접 사용하여 soldier.moth의 답변을 더 단순화 할 수 있습니다.
var ParentView = Backbone.View.extend({
events: {
'click': 'onclick'
}
});
var ChildView = ParentView.extend({
events: _.extend({}, ParentView.prototype.events, {
'click' : 'onclickChild'
})
});
내가 좋아하는 패턴은 생성자를 수정하고 몇 가지 추가 기능을 추가하는 것입니다.
// App View
var AppView = Backbone.View.extend({
constructor: function(){
this.events = _.result(this, 'events', {});
Backbone.View.apply(this, arguments);
},
_superEvents: function(events){
var sooper = _.result(this.constructor.__super__, 'events', {});
return _.extend({}, sooper, events);
}
});
// Parent View
var ParentView = AppView.extend({
events: {
'click': 'onclick'
}
});
// Child View
var ChildView = ParentView.extend({
events: function(){
return this._superEvents({
'click' : 'onclickChild'
});
}
});
부모를 식별 할 필요가 없기 때문에이 방법을 선호합니다. attributes
및에 대해 동일한 논리를 사용합니다 defaults
.
와, 여기에 많은 답변이 있지만 하나 더 제공 할 것이라고 생각했습니다. BackSupport 라이브러리를 사용하는 경우 extend2
. 사용 extend2
하면 자동으로 병합 events
( defaults
및 유사한 속성)이 처리됩니다.
다음은 간단한 예입니다.
var Parent = BackSupport.View.extend({
events: {
change: '_handleChange'
}
});
var Child = parent.extend2({
events: {
click: '_handleClick'
}
});
Child.prototype.events.change // exists
Child.prototype.events.click // exists
extend2
)은 제가 생각해 낼 수있는 최고 였고, 그렇게 끔찍하다고 생각하지 않습니다. Backbone에 익숙한 사람은 이미를 사용하는 데 익숙해 extend
져 있으므로 새로운 명령을 외울 필요가 없습니다.