ব্যাকবোন ভিউ: পিতামাতার কাছ থেকে ইভেন্টগুলি উত্তরাধিকারীকরণ এবং প্রসারিত করুন


115

ব্যাকবোন এর ডকুমেন্টেশন বলে:

ইভেন্টগুলির সম্পত্তিটিকে একটি ক্রিয়াকলাপ হিসাবে সংজ্ঞায়িত করা যেতে পারে যা কোনও ইভেন্ট হ্যাশ ফেরত দেয়, যাতে আপনার ইভেন্টগুলিকে প্রোগ্রামালিটিকভাবে সংজ্ঞায়িত করা সহজ হয়, পাশাপাশি পিতামাতার দর্শন থেকে উত্তরাধিকারী হয়।

আপনি কীভাবে পিতামাতার দৃশ্যের ইভেন্টগুলি উত্তরাধিকারী হন এবং সেগুলি প্রসারিত করবেন?

মূল দৃষ্টিভঙ্গি

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

শিশু দেখুন

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

উত্তর:


189

একটি উপায়:

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

ইভেন্টগুলি ফাংশন বা অবজেক্ট কিনা তা পরীক্ষা করতে To

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

এটি দুর্দান্ত ... সম্ভবত আপনি চাইল্ডভিউ থেকে কীভাবে উত্তরাধিকারী হবেন তা দেখানোর জন্য এটি আপডেট করতে পারেন (প্রোটোটাইপ ইভেন্টগুলি কোনও ফাংশন বা অবজেক্ট কিনা তা পরীক্ষা করুন) ... অথবা সম্ভবত আমি পুরো উত্তরাধিকারের জিনিসগুলি ছাড়িয়ে যাচ্ছি।
ব্রেন্ট করুন

@ ব্রেন্ট শিওর, সবেমাত্র তৃতীয় কেস যুক্ত হয়েছে
সৈনিক.মথ

14
যদি আমি ভুল না হয়ে থাকি তবে আপনাকে কোনও ফাংশন parentEvents = _.result(ParentView.prototype, 'events');কিনা eventsতা 'ম্যানুয়ালি' পরীক্ষা করার পরিবর্তে ব্যবহার করতে সক্ষম হওয়া উচিত ।
কোয়েন

3
@Koen। আন্ডারস্কোর ইউটিলিটি ফাংশনটি উল্লেখ করার জন্য +1 _.result, যা আমি আগে লক্ষ্য করি নি। : যারা আগ্রহ দেখিয়েছে জন্য, এখানে এই থিমে বৈচিত্র একটি গুচ্ছ সঙ্গে একটি jsfiddle এর jsfiddle
EleventyOne

1
এখানে আমার দুটি সেন্ট নিক্ষেপ করতে, আমি বিশ্বাস করি যে দ্বিতীয় বিকল্পটি সর্বোত্তম সমাধান। নিছক সত্যের কারণেই আমি এটি বলছি যে এটিই কেবলমাত্র সত্য যা ইনপাসসুলেটেড method ব্যবহৃত একমাত্র প্রসঙ্গটি হ'ল thisউদাহরণ হিসাবে নাম দ্বারা পিতাম শ্রেণীর কল করা বনাম। এই জন্য আপনাকে অনেক ধন্যবাদ।
জেসি জেমস জ্যাকসন টেলর

79

সৈনিক.মোহর উত্তর ভাল একটি। এটিকে আরও সরলীকরণ করে আপনি কেবল নিম্নলিখিতটি করতে পারেন

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

তারপরে কেবল আপনার ইভেন্টগুলিকে উভয় শ্রেণিতেই সাধারণ উপায়ে সংজ্ঞা দিন।


8
ভাল কল, যদিও আপনি সম্ভবত অদলবদল করতে চান this.eventsএবং ParentView.prototype.eventsঅন্যথায় যদি উভয় একই ইভেন্টে হ্যান্ডলারগুলি সংজ্ঞায়িত করে তবে পিতামাতার হ্যান্ডলার সন্তানের উপর চাপিয়ে দেবে।
সৈনিক.মথ

1
@ সৈনিক.মথ, ঠিক আছে আমি এটিকে সম্পাদনা করেছি{},ParentView.prototype.events,this.events
এজেপি

1
স্পষ্টতই এটি কাজ করে, তবে আমি জানি, delegateEventsইভেন্টগুলিকে আবদ্ধ করার জন্য কনস্ট্রাক্টরে ডাকা হয়। সুতরাং আপনি যখন এটি প্রসারিত করবেন initialize, কীভাবে আসবেন যে খুব বেশি দেরি হয়নি?
সেলিমওবার

2
এটি নিট-পিক, তবে এই সমাধানটির সাথে আমার সমস্যাটি হ'ল: আপনার যদি ভিন্ন ভিন্ন এবং প্রচুর মতামত রয়েছে, তবে আপনি initializeকিছুটা ক্ষেত্রে অনিবার্যভাবে নিজেকে লিখতে পারবেন (তারপরেও সেই ফাংশনটির শ্রেণিবিন্যাস পরিচালনা করার সাথে মোকাবিলা করার জন্য) কেবলমাত্র ইভেন্ট অবজেক্টগুলি মার্জ করুন। eventsনিজের মধ্যে মার্জিং রাখতে আমার কাছে আরও ক্লিনার মনে হচ্ছে। বলা হচ্ছে, আমি এই পদ্ধতির কথা চিন্তা করতাম না, এবং জিনিসগুলি
অন্যরকমভাবে

1
এই উত্তরটি আর বৈধ নয় কারণ ডেলিগেটএভেন্টসকে আরম্ভ করার আগে ডাকা হয় (এটি 1.2.3 সংস্করণে সত্য) - টীকাগুলির উত্সে এটি সহজ।
রোয়

12

আপনি defaultsখালি বস্তু তৈরি এড়াতে পদ্ধতিটিও ব্যবহার করতে পারেন {}

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

2
এটি বাচ্চা হ্যান্ডলারের পরে পিতামাতাদের পরিচালনা করতে বাধ্য করে। বেশিরভাগ ক্ষেত্রেই সমস্যা নয়, তবে যদি কোনও শিশু ইভেন্টটি কোনও পিতামাতার ইভেন্টটি বাতিল (ওভাররাইড না করে) হয় তবে এটি সম্ভব নয়।
কোয়েন

10

আপনি যদি কফিস্ক্রিপ্ট ব্যবহার করেন এবং এতে কোনও ফাংশন সেট করেন তবে আপনি ব্যবহার eventsকরতে পারেন super

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

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

এটি কেবল তখনই কাজ করে যদি পিতামাতার ইভেন্টগুলি পরিবর্তনশীল কোনও বস্তুর পরিবর্তে কোনও ফাংশন হয়।
মাইকেল

6

ব্যাকবোন থেকে বিশেষায়িত বেস কন্সট্রাক্টর তৈরি করা কি সহজ হবে না iew দেখুন যা ঘটনাক্রমের উত্তরাধিকারকে পরিচালনা করে।

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: ....
} 

একটি বিশেষ দৃষ্টিভঙ্গি তৈরি করে: বেসভিউ যা প্রসারিত ফাংশনটিকে নতুন করে সংজ্ঞায়িত করে, আমাদের এমন সাবউভিউ থাকতে পারে (যেমন অ্যাপভিউ, সেকশনভিউ) যা তাদের পিতামাতার দৃশ্যের ঘোষিত ইভেন্টগুলি কেবল বেসভিউ বা এর কোনও ডেরিভেটিভ থেকে প্রসারিত করে তা করতে চায়।

আমরা আমাদের সাবভিউগুলিতে প্রোগ্রামের ক্রিয়াকলাপ হিসাবে আমাদের ইভেন্ট ফাংশনগুলি সংজ্ঞায়িত করার প্রয়োজনীয়তা এড়াতে পারি, যা বেশিরভাগ ক্ষেত্রে স্পষ্টতই পিতামাত্ত নির্মাণকারীকে উল্লেখ করা প্রয়োজন।


2

@ সৈনিক.মথের শেষ পরামর্শটির সংক্ষিপ্ত সংস্করণ:

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

2

এটিও কাজ করবে:

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

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

স্ট্রেইট ব্যবহার করা superআমার পক্ষে কাজ করে না, হয় ম্যানুয়ালি specParentView বা উত্তরাধিকার সূত্রে প্রাপ্ত শ্রেণিটি

অ্যাক্সেস _superVar যা কোনো coffeescript মধ্যে উপলব্ধClass … extends …


2

// 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

ব্যাকবোন সংস্করণ 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",
}

1

আমি এই নিবন্ধে আরও আকর্ষণীয় সমাধান খুঁজে পেয়েছি

এটি ব্যাকবোন এর সুপার এবং ইসিএমএস স্ক্রিপ্ট এর হ'ল ওয়ানপ্রোপার্টি ব্যবহার করে। এর প্রগতিশীল উদাহরণগুলির দ্বিতীয়টি কবজটির মতো কাজ করে। এখানে কিছুটা কোড রয়েছে:

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);
    },
    ...
});

আপনি এটি ইউআই এবং বৈশিষ্ট্যের জন্যও করতে পারেন ।

এই উদাহরণটি কোনও ফাংশন দ্বারা নির্ধারিত বৈশিষ্ট্যগুলির যত্ন নেয় না, তবে নিবন্ধের লেখক সেই ক্ষেত্রে একটি সমাধান সরবরাহ করে।


1

পুরোপুরি পিতামাত্ত শ্রেণিতে এটি করা এবং শিশু শ্রেণিতে একটি ফাংশন-ভিত্তিক ইভেন্ট হ্যাশ সমর্থন করা যাতে শিশুরা উত্তরাধিকারের অজ্ঞাব্য হতে পারে ( 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);
    };
  }
});

0

এই কফিস্ক্রিপ্ট সমাধানটি আমার পক্ষে কাজ করেছে (এবং @ সৈনিক.মথের পরামর্শটি বিবেচনা করে):

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

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

0

আপনি যদি নিশ্চিত হন যে ParentViewইভেন্টগুলিকে অবজেক্ট হিসাবে সংজ্ঞায়িত করা হয়েছে এবং আপনার ইভেন্টগুলি গতিশীলভাবে সংজ্ঞায়িত করার দরকার নেই ChildViewতবে সৈনিকের পক্ষে আরও সহজ করা সম্ভব oth মথের উত্তরটি আরও ফাংশন থেকে মুক্তি পেয়ে এবং _.extendসরাসরি ব্যবহার করে:

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

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

0

এর জন্য একটি প্যাটার্নটি আমি পছন্দ করি যা নির্মাণকারীকে সংশোধন করে কিছু অতিরিক্ত কার্যকারিতা যুক্ত করছে:

// 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


0

বাহ, এখানে প্রচুর উত্তর তবে আমি ভেবেছিলাম যে আমি আরও একটি প্রস্তাব দেব। আপনি যদি ব্যাকসপোর্ট লাইব্রেরি ব্যবহার করেন তবে এটি অফার করে 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

https://github.com/machineghost/BackSupport


3
আমি ধারণাটি পছন্দ করি, তবে কেবলমাত্র নীতিগতভাবে, আমি এমন কোনও লাইব্রেরিতে পাস করতাম যা মনে করে "এক্সটেনড 2" একটি সঠিক ফাংশনের নাম।
ইয়ানিভ

মূলত "ব্যাকবোন.একস্ট্যান্ড, তবে উন্নত কার্যকারিতা সহ" এমন কোনও ফাংশনটির নামকরণ করার জন্য আপনি যে প্রস্তাব দিতে পারেন তার আমি স্বাগত জানাব। এক্সটেন্ডেড ২.০ ( extend2) আমি যে সর্বোত্তমভাবে সামনে আসতে পেরেছিলাম তা আমি মনে করি না এবং extendএগুলি এত ভয়াবহ বলে মনে হয়: ব্যাকবোন ব্যবহার করা যে কেউ ইতিমধ্যে ব্যবহারে অভ্যস্ত , সুতরাং এইভাবে তাদের কোনও নতুন কমান্ড মুখস্থ করার দরকার নেই।
মেশিনঘোস্ট

এটি সম্পর্কে গিথুব রেপোতে একটি সমস্যা খোলে। :)
ইয়ানিভ
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.