Idbone.js विचारों में गतिशील रूप से id और className सेट करना


85

मैं Backbone.js सीखने और उपयोग करने की प्रक्रिया में हूं।

मेरे पास एक आइटम मॉडल और एक संबंधित आइटम दृश्य है। प्रत्येक मॉडल के उदाहरण में item_class और Item_id विशेषताएँ होती हैं, जिन्हें मैं 'id' और 'class' के रूप में संगत दृश्य के रूप में प्रतिबिंबित करना चाहता हूं। इसे प्राप्त करने का सही तरीका क्या है?

उदाहरण:

var ItemModel = Backbone.Model.extend({      
});

var item1 = new ItemModel({item_class: "nice", item_id: "id1"});
var item2 = new ItemModel({item_class: "sad", item_id: "id2"});

var ItemView = Backbone.View.extend({       
});

मुझे दृश्य को कैसे लागू करना चाहिए ताकि विचारों का el 'में अनुवाद हो जाए:

<div id="id1" class="nice"></div>
<div id="id2" class="sad"> </div>

अधिकांश उदाहरणों में मैंने देखा है, दृश्य के एल एक अर्थहीन आवरण तत्व के रूप में कार्य करता है, जिसके अंदर किसी को मैन्युअल रूप से 'शब्दार्थ' कोड लिखना होता है।

var ItemView = Backbone.View.extend({
   tagName:  "div",   // I know it's the default...

   render: function() {
     $(this.el).html("<div id="id1" class="nice"> Some stuff </div>");
   }       
});

इसलिए जब प्रदान किया जाता है, तो एक हो जाता है

<div> <!-- el wrapper -->
    <div id="id1" class="nice"> Some stuff </div>
</div>

लेकिन यह एक बर्बादी की तरह लगता है - बाहरी विभाजन क्यों है? मैं चाहता हूं कि एल सीधे आंतरिक div में अनुवाद करे!

जवाबों:


133

सारांश: मॉडल डेटा के साथ गतिशील रूप से सेट दृश्य विशेषताएँ

http://jsfiddle.net/5wd0ma8b/

// View class with `attributes` method
var View = Backbone.View.extend( {
  attributes : function () {
    // Return model data
    return {
      class : this.model.get( 'item_class' ),
      id : this.model.get( 'item_id' )
    };
  }
  // attributes
} );

// Pass model to view constructor
var item = new View( {
  model : new Backbone.Model( {
    item_class : "nice",
    item_id : "id1"
  } )
} );
  • यह उदाहरण मानता है कि आप Backbone को आपके लिए DOM तत्व उत्पन्न करने की अनुमति दे रहे हैं।

  • attributesबाद गुण दृश्य निर्माता के लिए पारित सेट कर रहे हैं विधि कहा जाता है (इस मामले में, model), आप गतिशील मॉडल डेटा के साथ विशेषताओं से पहले रीढ़ बनाता है स्थापित करने के लिए अनुमति देता el।

  • कुछ अन्य उत्तरों के विपरीत: दृश्य वर्ग में हार्ड-कोड विशेषता मान नहीं है, गतिशील रूप से उन्हें मॉडल डेटा से सेट करता है; render()Attr vals सेट होने तक प्रतीक्षा न करें ; बार-बार प्रत्येक कॉल के लिए attr vals सेट नहीं करता render(); अनावश्यक रूप से DOM तत्व पर मैन्युअल रूप से attr वैल सेट नहीं करता है।

  • ध्यान दें कि यदि वर्ग जब बुला की स्थापना Backbone.View.extendया एक दृश्य के निर्माता (जैसे new Backbone.View), आप डोम संपत्ति नाम का उपयोग करना, className, लेकिन अगर के माध्यम से इसे स्थापित करने attributesहैश / विधि (इस उदाहरण में के रूप में) आप विशेषता नाम का उपयोग करना, class।

  • रीढ़ की हड्डी के रूप में 0.9.9:

    जब एक दृश्य की घोषणा ... el, tagName, idऔर classNameअब कार्यों के रूप में परिभाषित किया जा सकता है, अगर आप चाहते हैं उनके मूल्यों रनटाइम पर निर्धारित किया जाना।

    मैं इस मामले में इसका उल्लेख करता हूं कि ऐसी स्थिति है जहां यह attributesसचित्र के रूप में एक विधि का उपयोग करने के विकल्प के रूप में उपयोगी होगा ।

किसी मौजूदा तत्व का उपयोग करना

यदि आप किसी मौजूदा तत्व का उपयोग कर रहे हैं (जैसे elव्यू कंस्ट्रक्टर को पास करना) ...

var item = new View( { el : some_el } );

... तो attributesतत्व पर लागू नहीं किया जाएगा। यदि वांछित विशेषताएँ पहले से ही तत्व पर सेट नहीं हैं, या आप उस डेटा को अपने दृश्य वर्ग और किसी अन्य स्थान पर डुप्लिकेट नहीं करना चाहते हैं, तो आप initializeअपने व्यू कंस्ट्रक्टर में एक विधि जोड़ना चाह सकते हैं जो लागू होता attributesहै el। कुछ इस तरह (उपयोग करते हुए jQuery.attr):

View.prototype.initialize = function ( options ) {
  this.$el.attr( _.result( this, 'attributes' ) );
};

elआवरण से बचने, रेंडरिंग का उपयोग

अधिकांश उदाहरणों में मैंने देखा है, दृश्य के एल एक अर्थहीन आवरण तत्व के रूप में कार्य करता है, जिसके अंदर किसी को मैन्युअल रूप से 'शब्दार्थ' कोड लिखना होता है।

कोई कारण नहीं view.elहै "एक अर्थहीन आवरण तत्व" होने की आवश्यकता है। वास्तव में, यह अक्सर DOM संरचना को तोड़ देगा। यदि कोई दृश्य वर्ग <li>उदाहरण के लिए एक तत्व का प्रतिनिधित्व करता है , तो उसे एक <li>- <div>या इसे किसी अन्य तत्व के रूप में प्रस्तुत करते हुए सामग्री मॉडल को तोड़ना होगा। आप की संभावना सही ढंग से अपने दृश्य के तत्व की स्थापना (जैसे गुणों का उपयोग करके पर ध्यान केंद्रित करना चाहते हैं tagName, classNameऔर id) और फिर अपने प्रतिपादन सामग्री उसके बाद।

डोम के साथ बातचीत करने के लिए आपके बैकबोन व्यू ऑब्जेक्ट्स के लिए विकल्प व्यापक खुले हैं। 2 मूल प्रारंभिक परिदृश्य हैं:

  • आप किसी मौजूदा DOM तत्व को बैकबोन दृश्य में संलग्न कर सकते हैं।

  • आप बैकबोन को एक नया तत्व बनाने की अनुमति दे सकते हैं जो दस्तावेज़ से डिस्कनेक्ट हो गया है, फिर किसी तरह इसे दस्तावेज़ में डालें।

ऐसे विभिन्न तरीके हैं जिनसे आप तत्व के लिए सामग्री तैयार कर सकते हैं (शाब्दिक स्ट्रिंग सेट करें, जैसा कि आपके उदाहरण में, एक टेंपलेटिंग लाइब्रेरी जैसे मूंछें, हैंडलबार इत्यादि का उपयोग करें)। आपको कैसे उपयोग करना चाहिएel दृश्य संपत्ति का निर्भर करता है कि आप क्या कर रहे हैं।

विद्यमान तत्व

आपके रेंडरिंग उदाहरण से पता चलता है कि आपके पास एक मौजूदा तत्व है जिसे आप दृश्य में असाइन कर रहे हैं, हालांकि आप विचारों का इंस्टेंटेशन नहीं दिखाते हैं। यदि ऐसा है, और तत्व पहले से ही दस्तावेज़ में है, तो आप ऐसा कुछ करना चाह सकते हैं (सामग्री को अपडेट करें el, लेकिन elस्वयं को परिवर्तित न करें ):

render : function () {
  this.$el.html( "Some stuff" );
}

http://jsfiddle.net/vQMa2/1/

जनित तत्व

मान लें कि आपके पास कोई मौजूदा तत्व नहीं है और आप बैकबोन को आपके लिए एक जेनरेट करने की अनुमति देते हैं। आप ऐसा कुछ करना चाह सकते हैं (लेकिन यह बेहतर है कि आर्किटेक्ट चीजों को बेहतर बनाया जाए ताकि आपका नजरिया खुद के बारे में कुछ भी जानने के लिए जिम्मेदार न हो):

render : function () {
  this.$el.html( "Some stuff" );
  $( "#some-container" ).append( this.el );
}

http://jsfiddle.net/vQMa2/

टेम्पलेट्स

मेरे मामले में, मैं टेम्पलेट्स का उपयोग कर रहा हूं, उदाहरण के लिए:

<div class="player" id="{{id}}">
<input name="name" value="{{name}}" />
<input name="score" value="{{score}}" />
</div>
<!-- .player -->

टेम्पलेट संपूर्ण दृश्य का प्रतिनिधित्व करता है। दूसरे शब्दों में, टेम्पलेट के आसपास कोई आवरण नहीं होगा -div.player होगा मेरे विचार का मूल या सबसे बाहरी तत्व होगा।

मेरा खिलाड़ी वर्ग कुछ इस तरह दिखाई देगा (बहुत सरलीकृत उदाहरण के साथ render()):

Backbone.View.extend( {
  tagName : 'div',
  className : 'player',

  attributes : function () {
    return {
      id : "player-" + this.model.cid
    };
  },
  // attributes

  render : function {
    var rendered_template = $( ... );

    // Note that since the top level element in my template (and therefore
    // in `rendered_template`) represents the same element as `this.el`, I'm
    // extracting the content of `rendered_template`'s top level element and
    // replacing the content of `this.el` with that.
    this.$el.empty().append( rendered_template.children() );
  }      
} );

किसी फ़ंक्शन के साथ गुण गुण को अधिलेखित करने और किसी ऑब्जेक्ट को फिर से वापस करने का भयानक तरीका!
— केल

2
@ हाँ, यह एक अच्छा तरीका है कि किसी प्रश्न के लिए डायनामिक को पूरा करने का एक अच्छा तरीका है, जो मॉडल डेटा के साथ विशेषताओं को पॉप्युलेट करता है, दोहराए गए कोड का उपयोग किए बिना जहां विचारों को त्वरित किया जाता है। आप शायद यह जानते हैं, लेकिन अगर यह स्पष्ट नहीं है, तो यह बैकबोन की एक विशेषता है कि आप एक फ़ंक्शन का उपयोग कर सकते हैं जो एक हैश को मान देता है attributes, जैसे कि अन्य बैकबोन गुणों की संख्या जो फ़ंक्शन या कुछ अन्य के रूप में आपूर्ति की जा सकती है मूल्य का प्रकार। उन मामलों में बैकबोन जांचता है कि क्या मान एक फ़ंक्शन है, इसे कॉल करता है, और रिटर्न मूल्य का उपयोग करता है।
— जेएमएम

95

आपके विचार में बस कुछ ऐसा है

var ItemView = Backbone.View.extend({
   tagName:  "div",   // I know it's the default...

   render: function() {
     $(this.el).attr('id', 'id1').addClass('nice').html('Some Stuff'); 
   }       
});

यह इस प्रश्न का सही उत्तर है और इसे स्वीकार किया जाना चाहिए
— 15

13
यह उत्तर मॉडल डेटा के आधार पर दृश्य विशेषताओं को गतिशील रूप से सेट करने के लिए प्रदर्शित नहीं करता है, यह सिर्फ विशेषता मानों को हार्ड-कोडिंग का एक वैकल्पिक तरीका दिखाता है।
— JMM

3
@ जेएमएम - उसका नमूना कोड या तो मॉडल डेटा का उपयोग नहीं कर रहा है। यह उत्तर उसके नमूना कोड के आधार पर काम करता है। जाहिर है कि मॉडल डेटा को मूल्यों के लिए प्रतिस्थापित किया जा सकता है।
— क्लिंट

5
@ क्लिंट, मैं ओपी के लिए स्पष्ट होने पर भरोसा नहीं करूंगा। "उसका नमूना कोड या तो मॉडल डेटा का उपयोग नहीं कर रहा है।" - ऐसा इसलिए है क्योंकि वह नहीं जानता कि कैसे, और इसलिए उसने मदद क्यों मांगी। यह मुझे स्पष्ट लगता है कि वह पूछ रहा है कि मॉडल डेटा का उपयोग करके दृश्य के सेट कैसे सेट करें और इसके बारे में जाने का कोई विचार नहीं है। उत्तर यह भी नहीं दिखाता है कि ऐसा कैसे करना है, और आप इसे वैसे भी करने के लिए तब तक इंतजार क्यों करेंगे, या हर बार जब आप इसे प्रस्तुत करते हैं, तो फिर से करते हैं? "यह जवाब काम करता है ..." - यह कैसे काम करता है? प्रत्येक दृश्य को उसी तरह बनाया जाएगा जिसमें एक ही एटर वेल होगा। केवल एक चीज यह दिखाती है कि रैपर से कैसे बचा जाए।
— JMM

फ़रवरी 12 से ओपी चला गया है। :( यहाँ इस जवाब के लिए एक और +1 है।
— अल्मो

27

आप गुण classNameऔर idरूट तत्व पर सेट कर सकते हैं : http://documentcloud.github.com/backbone/#View-extend

var ItemView = Backbone.View.extend({
   tagName:  "div",   // I know it's the default...
   className : 'nice',
   id : 'id1',
   render: function() {
     $(this.el).html("Some stuff");
   }       
});

EDIT में कंस्ट्रक्टर मापदंडों के आधार पर आईडी सेट करने का उदाहरण शामिल है

यदि विचारों का निर्माण किया गया है, जैसा कि उल्लेख किया गया है:

var item1 = new ItemModel({item_class: "nice", item_id: "id1"});
var item2 = new ItemModel({item_class: "sad", item_id: "id2"});

तब मूल्यों को इस तरह से सेट किया जा सकता है:

// ...
className: function(){
    return this.options.item_class;
},
id: function(){
    return this.options.item_id;
}
// ...

3
मुझे यह उत्तर सही नहीं लगता है क्योंकि तब प्रत्येक के ItemViewपास होगा id: 'id1'। इस पर आधारित निष्पादन समय में गणना की जानी है model.id।
— fguillen

आप निश्चित रूप से आईडी को किसी भी तरह से सेट कर सकते हैं। फंक्शन, वेरिएबल या किसी भी चीज का इस्तेमाल करें। मेरे कोड में केवल एक उदाहरण शामिल है, यह बताता है कि रूट तत्व पर मान कैसे सेट किया जाए।
— जोर्जेन

मैंने एक उदाहरण जोड़ते हुए स्पष्ट किया है कि निर्माण मानकों के आधार पर गतिशील रूप से मूल्यों को कैसे सेट किया जाए।
— जोर्जेन

यह सही जवाब है। यह समस्या को हल करने के लिए बैकबोन सुविधाओं का सही ढंग से उपयोग करता है।
— मार्क-एंटोनी लेमीक्स

6

मुझे पता है कि यह एक पुराना प्रश्न है, लेकिन संदर्भ के लिए जोड़ा गया है। नए बैकबोन संस्करणों में यह आसान लगता है। बैकबोन 1.1 में आईडी और क्लासनाम गुणों का मूल्यांकन फ़ंक्शन में किया जाता है ensureElement( स्रोत से देखें ) अंडरस्कोर _.resultअर्थ का उपयोग करते हुए यदि classNameयाid कोई फ़ंक्शन है , तो उसे कॉल किया जाएगा, अन्यथा उसके मूल्य का उपयोग किया जाएगा।

तो आप सीधे क्लासनाम को कंस्ट्रक्टर में दे सकते हैं, एक और पैरामीटर दे सकते हैं जो क्लासनेम में उपयोग किया जाएगा, आदि ... बहुत सारे विकल्प

तो यह काम करना चाहिए

var item1 = new ItemModel({item_class: "nice", item_id: "id1"});
var item2 = new ItemModel({item_class: "sad", item_id: "id2"});

var ItemView = Backbone.View.extend({       
  id: function() { return this.model.get('item_id'); },
  className: function() { return this.model.get('item_class'); }
});

आपका उदाहरण मान्य नहीं है, आप चाहते हैंid: function() { return this.model.get('item_id'); })
— Cobe

4

अन्य उदाहरण नहीं दिखा रहे हैं कि वास्तव में मॉडल से डेटा कैसे हड़पना है। मॉडल के डेटा से आईडी और क्लास को गतिशील रूप से जोड़ने के लिए:

var ItemView = Backbone.View.extend({
   tagName:  "div",

   render: function() {
     this.id = this.model.get('item_id');
     this.class = this.model.get('item_class');
     $(this.el).attr('id',this.id).addClass(this.class).html('Some Stuff'); 
   }       
});

वह 'यह.क्लासनाम' या 'दिस.क्लास' है?
— गेब रेनबो

2

आपको टैगनेम को हटाने और एल घोषित करने की आवश्यकता है।

'tagName' दर्शाता है कि आप एक तत्व बनाना चाहते हैं। यदि तत्व पहले से ही डोम में मौजूद है, तो आप एक एल निर्दिष्ट कर सकते हैं जैसे:

el: $('#emotions'),

और बादमें:

render: function() { 
     $(this.el).append(this.model.toJSON());
}

2

मान को इनिशियलाइज़ विधि से असाइन करने का प्रयास करें यह सीधे आईडी और डिविजन को डायनेमिक रूप से असाइन करेगा।

var ItemView = Backbone.View.extend( {
    tagName : "div",   
    id      : '',
    class   : '',

    initialize : function( options ) {
        if ( ! _.isUndefined( options ) ) {
            this.id = options.item_id;
            this.class= options.item_class;
        }
    },

    render : function() {
        $( this.el ).html( this.template( "stuff goes here" ) ); 
    }
} );

@ मिचेल प्लेसे ने इस प्रलेखन को जाना, backbonejs.org/#View-constructor
— हेमंत

0

यहां किसी मॉडल के माध्यम से दृश्य तत्व के वर्ग को बदलने और मॉडल परिवर्तनों पर अपडेट करने का एक न्यूनतम तरीका है।

var VMenuTabItem = Backbone.View.extend({
    tagName: 'li',
    events: {
        'click': 'onClick'
    },
    initialize: function(options) {

        // auto render on change of the class. 
        // Useful if parent view changes this model (e.g. via a collection)
        this.listenTo(this.model, 'change:active', this.render);

    },
    render: function() {

        // toggle a class only if the attribute is set.
        this.$el.toggleClass('active', Boolean(this.model.get('active')));
        this.$el.toggleClass('empty', Boolean(this.model.get('empty')));

        return this;
    },
    onClicked: function(e) {
        if (!this.model.get('empty')) {

            // optional: notify our parents of the click
            this.model.trigger('tab:click', this.model);

            // then update the model, which triggers a render.
            this.model.set({ active: true });
        }
    }
});
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.