development

백본보기 : 상위에서 이벤트 상속 및 확장

big-blog 2020. 7. 25. 10:16
반응형

백본보기 : 상위에서 이벤트 상속 및 확장


백본의 설명서 상태 :

events 속성은 이벤트 해시를 반환하는 함수로 정의되어 이벤트를 프로그래밍 방식으로 쉽게 정의하고 상위 뷰에서 상속 할 수 있습니다.

부모의 뷰 이벤트를 어떻게 상속하고 확장합니까?

부모보기

var ParentView = Backbone.View.extend({
   events: {
      'click': 'onclick'
   }
});

어린이보기

var ChildView = ParentView.extend({
   events: function(){
      ????
   }
});

한 가지 방법은 다음과 같습니다.

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'
      });
   }
});

군인. 나방 대답은 좋은 것입니다. 더 단순화하면 다음을 수행 할 수 있습니다.

var ChildView = ParentView.extend({
   initialize: function(){
       _.extend(this.events, ParentView.prototype.events);
   }
});

그런 다음 일반적인 방법으로 클래스 중 하나에서 이벤트를 정의하십시오.


defaults방법을 사용 하여 빈 객체를 만들지 않아도 {}됩니다.

var ChildView = ParentView.extend({
  events: function(){
    return _.defaults({
      'click' : 'onclickChild'
    }, ParentView.prototype.events);
  }
});

CoffeeScript를 사용하고 기능을로 설정 events하면을 사용할 수 있습니다 super.

class ParentView extends Backbone.View
  events: ->
    'foo' : 'doSomething'

class ChildView extends ParentView
  events: ->
    _.extend {}, super,
      'bar' : 'doOtherThing'

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
}

이를 통해 재정의 된 extend 함수를 사용하여 새로운 '서브 클래스'(자식 생성자)를 생성 할 때마다 이벤트 해시를 계층 구조로 축소 (병합) 할 수 있습니다.

# 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 또는 그 파생물 중 하나에서 확장함으로써 간단하게 만들 수 있습니다.

우리는 서브 뷰에서 이벤트 함수를 프로그래밍 방식으로 정의 할 필요가 없으며 대부분의 경우 상위 생성자를 명시 적으로 참조해야합니다.


@ soldier.moth의 마지막 제안에 대한 짧은 버전 :

var ChildView = ParentView.extend({
  events: function(){
    return _.extend({}, _.result(ParentView.prototype, 'events') || {}, {
      'click' : 'onclickChild'
    });
  }
});

이것은 또한 작동합니다 :

class ParentView extends Backbone.View
  events: ->
    'foo' : 'doSomething'

class ChildView extends ParentView
  events: ->
    _.extend({}, _.result(_super::, 'events') || {},
      'bar' : 'doOtherThing')

straight super사용하는 것은 효과가 없었습니다 ParentView. 또는 상속 된 클래스를 수동으로 지정했습니다 .

_super모든 커피 스크립트에서 사용할 수 있는 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 */ }
});

http://danhough.com/blog/backbone-view-inheritance/


백본 버전 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",
}

기사 에서 더 흥미로운 해결책을 찾았습니다.

백본의 수퍼 및 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);
    },
    ...
});

uiattributes에 대해서도이를 수행 할 수 있습니다 .

This example does not take care of the properties set by a function, but the author of the article offers a solution in that case.


This CoffeeScript solution worked for me (and takes into account @soldier.moth's suggestion):

class ParentView extends Backbone.View
  events: ->
    'foo' : 'doSomething'

class ChildView extends ParentView
  events: ->
    _.extend({}, _.result(ParentView.prototype, 'events') || {},
      'bar' : 'doOtherThing')

If you are sure that the ParentView has the events defined as object and you don't need to define events dynamically in ChildView it is possible to simplify soldier.moth's answer further by getting rid of the function and using _.extend directly:

var ParentView = Backbone.View.extend({
    events: {
        'click': 'onclick'
    }
});

var ChildView = ParentView.extend({
    events: _.extend({}, ParentView.prototype.events, {
        'click' : 'onclickChild'
    })
});

A pattern for this that I am fond of is modifying the constructor and adding some additional functionality:

// 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'
        });
    }

});

I prefer this method because you do not have to identify the parent -one less variable to change. I use the same logic for attributes and defaults.


Wow, lots of answers here but I thought I'd offer one more. If you use the BackSupport library, it offers extend2. If you use extend2 it automatically takes care of merging events (as well as defaults and similar properties) for you.

Here's a quick example:

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

https://github.com/machineghost/BackSupport


To do this entirely in the parent class and support a function-based events hash in the child class so that children can be agnostic of inheritance (the child will have to call MyView.prototype.initialize if it overrides 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);
    };
  }
});

참고URL : https://stackoverflow.com/questions/9403675/backbone-view-inherit-and-extend-events-from-parent

반응형