2014-09-18 10 views
6

मैं रीढ़ की हड्डी के लिए बिल्कुल नया हूं और मैं ज़ोंबी विचारों के इन्स और बहिष्कार को समझने की कोशिश करता हूं।बैकबोन ज़ोंबी विचार और अच्छी प्रैक्टिस

एक ज़ोंबी इस article के अनुसार, यह है:

जब हम घटनाओं के माध्यम से एक साथ वस्तुओं के लिए बाध्य लेकिन हम उन्हें अनबाइंडिंग परेशान नहीं है। जब तक ये वस्तुएं एक साथ बंधी हुई हों, और हमारे ऐप कोड में उनमें से कम से कम एक संदर्भ है, तो उन्हें साफ़ नहीं किया जाएगा या कचरा एकत्र नहीं किया जाएगा। परिणामस्वरूप स्मृति रिसाव फिल्मों की लाश की तरह हैं - अंधेरे कोनों में छिपकर, बाहर निकलने और हमें दोपहर के भोजन के लिए खाने का इंतजार कर रहे हैं।

उपर्युक्त आलेख एक ऐसा ऑब्जेक्ट बनाने का सुझाव देता है जो दृश्यों के बीच संक्रमण को प्रबंधित करता है और फिर दृश्य को हटाने और अनदेखा करने के लिए एक करीबी फ़ंक्शन को लागू करने के लिए सुझाव देता है।

कहा जा रहा है कि स्थिति के आधार पर, उस करीबी कार्य को कहां से कॉल करें?

मैं बच्चे के दृश्य का पता लगाने के लिए अपने मूल दृश्य के प्रारंभिक ब्लॉक में एक संपत्ति जोड़ता हूं। इस तरह से मैं इसे एक नए द्वारा प्रतिस्थापित करने से पहले .remove() पर कॉल करने में सक्षम हूं। क्या यह अच्छा अभ्यास है या क्या कोई बेहतर तरीका है?

मैं भी समझ में नहीं आता क्यों el को परिभाषित करने और फिर

this.$el.html(this.template(this.model.attributes));

साथ प्रतिपादन मुझे देखने निकल करने के लिए काम करता है, जबकि यह रूप में

$('#sportsManDetails').html(this.$el.html(this.template(this.model.attributes)));

करके की उम्मीद की अनुमति नहीं है

उदाहरण के लिए, मैंने अभी एक साधारण ऐप बनाया है जो खिलाड़ियों के नामों की एक सूची प्रदर्शित करता है और जो किसी नाम पर क्लिक करते समय अधिक जानकारी दिखाता है।

यहाँ कोड और एक काम कर fiddle है:

एचटीएमएल

<script id="nameListTemplate" type="text/template"> 
    <%= first %> <%= last %> 
</script> 
<script id="sportsManDetailsTemplate" type="text/template"> 
    <ul> 
     <li><%= first %></li> 
     <li><%= last %></li> 
     <li><%= age %></li> 
     <li><%= sport %></li> 
     <li><%= category %></li> 
    </ul> 
    <button class="test">Test</button> 
</script> 
<div id="sportsMenName"></div> 
<div id="sportsManDetails"></div> 

जे एस

मॉडल और संग्रह

var app = app || {}; 

app.SportsManModel = Backbone.Model.extend({}); 

app.SportsMenCollection = Backbone.Collection.extend({ 
    model: app.SportsManModel 
}); 

NameView

app.NameView = Backbone.View.extend({ 
    tagName: 'li', 
    className: 'sportsMan', 
    template: _.template($('#nameListTemplate').html()), 

    initialize: function(){ 
     this.sportsManDetailsView; 
    }, 

    events: { 
     'click': 'showSportsManDetails' 
    }, 

    showSportsManDetails: function(e){ 
     if (typeof this.sportsManDetailsView !== 'undefined'){ 
      this.sportsManDetailsView.remove(); 
     } 
     this.sportsManDetailsView = new app.SportsManDetailsView({ 
      model: this.model 
     }) 
    }, 

    render: function(){ 
     this.$el.append(this.template(this.model.attributes)); 
     return this; 
    } 
}); 

NameListView

app.NameListView = Backbone.View.extend({ 
    el: '#sportsMenName', 

    initialize: function(sportsMen){ 
     this.collection = new app.SportsMenCollection(sportsMen); 
     this.render(); 
    }, 

    render: function(){ 
     this.collection.each(function(sportsMen){ 
      this.renderContact(sportsMen); 
     }, this); 
    }, 

    renderContact: function(sportsMen){ 
     var nameView = new app.NameView({ 
      model: sportsMen 
     }); 
     this.$el.append(nameView.render().el); 
    } 
}); 

SportsManDetailsView

app.SportsManDetailsView = Backbone.View.extend({ 
    // doesn't work if I use el in conjunction with 
    // this.$el.html(this.template(this.model.attributes)); 
    // el: '#sportsManDetails', 
    template: _.template($('#sportsManDetailsTemplate').html()), 

    initialize: function(){ 
     this.render(); 
    }, 

    events: { 
     'click .test': 'test' 
    }, 

    test: function(){ 
     alert('test'); 
    }, 

    render: function(){      
     // that does not work 
     //this.$el.html(this.template(this.model.attributes)); 

     // is this good practice? 
     $('#sportsManDetails').html(this.$el.html(this.template(this.model.attributes))); 
    } 
}); 

ऐप।js

var sportsMen = [ 
    {first: 'Quentin', last: 'Tarant', age: '34', sport: 'bike', category: '- 90kg'}, 
    {first: 'Aymeric', last: 'McArthur', age: '54', sport: 'jetski', category: '200HP'}, 
    {first: 'Peter', last: 'TheFat', age: '45', sport: 'curling', category: 'dunno'}, 
    {first: 'Charles', last: 'Martel', age: '21', sport: 'Moto', category: 'MX 250cc'}, 
]; 

$(function(){ 
    new app.NameListView(sportsMen); 
}); 

उत्तर

6

साथ यह जाँच कर सकते हैं बस के रूप में आप खोज कर रहे है बनाओ, रीढ़ अपने आप में एक की तुलना में एक पुस्तकालय के अधिक समझता है ढांचा - यह डेवलपर को छोड़कर बहुत से प्रश्न और डिजाइन पैटर्न छोड़ देता है।

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

दृश्य के जीवन चक्र को प्रबंधित करने के लिए, आप अभिभावक दृश्य का उपयोग कर सकते हैं, लेकिन राउटर से ऐसा करना एक आम प्रथा है। रूटर का उपयोग पुराने विचारों को हटाने और रूट ईवेंट पर नए लोगों को तुरंत चालू करने के लिए किया जाता है। यहाँ की कैसे मैं अक्सर यह पूरा एक टुकड़ा है:

render: function(){ 
    this.mainView && this.mainView.remove();     // if there is already a view, remove it 
    this.mainView = new SomeOtherKindOfViewDeterminedBySomeEvent(); // instantiate the new view 
    this.mainView.render(); 
    this.mainView.$el.appendTo('#main-content');    // append it 
} 

कुछ बातें ध्यान रखें:

  1. स्पष्ट रूप से एक दृश्य पर remove बुला के बिना, अपने अनुप्रयोग मेमोरी लीक के लिए असुरक्षित हो जाएगा। ऐसा इसलिए है क्योंकि पृष्ठभूमि में दृश्य की घटनाएं और गुण अभी भी मौजूद हैं। उदाहरण के लिए, यदि आप ऊपर दिए गए उदाहरण की पहली पंक्ति को हटाते हैं, तो मैं पूर्व this.mainView पर अपना संदर्भ खो दूंगा, लेकिन यह घटनाएं अभी भी स्मृति का उपयोग कर रही हैं। इसका समय आपके ऐप पर प्रभाव डालेगा।
  2. ध्यान दें कि मैं अंतिम पंक्ति में appendTo का उपयोग कर रहा हूं। एक दृश्य पर remove पर कॉल करते समय, यह संपूर्ण तत्व हटा दिया जाता है, साथ ही साथ यह ईवेंट भी होता है। अगर मैं बस इस किया था:

    this.mainView = new SomeOtherKindOfViewDeterminedBySomeEvent({ el: '#main-content' })

    तब के बाद मैं this.mainView पर remove फोन, #main-content डोम से हटा दिया जाएगा किया गया है, इसलिए मैं अब उस का भी उपयोग कर सकते हैं। इसे जोड़कर, मैं प्लेसहोल्डर के रूप में #main-content रखता हूं, इसलिए मैं इसे दृश्य जोड़ना जारी रख सकता हूं। SportsManDetailsView को अनबिंड करने का प्रयास करते समय आप जो देख रहे हैं, उसे फिर से प्रस्तुत करें।

अपने प्रश्नों के लिए के रूप में, यह:

$('#sportsManDetails').html(this.$el.html(this.template(this.model.attributes)));

नहीं अच्छा अभ्यास है। यह पहला है कि आपने वैश्विक jQuery ऑब्जेक्ट का उपयोग किया है, जो बैकबोन के encapsulated विचारों के दृष्टिकोण को हरा देता है। दूसरा, घटनाएं अभी भी डीओएम में पूर्व विचारों से सक्रिय हैं, जिससे मेमोरी लीक हो जाती है। जब आप टेस्ट बटन पर क्लिक करते हैं तो आप इसे देख सकते हैं - प्रत्येक बार जब आप SportsManDetailsView को तुरंत चालू करते हैं तो हैंडलर फ़ंक्शन आग लग जाएगा (दूसरी बार, अलर्ट संदेश दो बार दिखाया जाएगा, फिर तीन बार इत्यादि।)

आपको इस तरह की बातचीत को संभालने के लिए अभिभावक दृश्य या राउटर पर भरोसा करना चाहिए। वह, या SportsManDetailsView#sportsManDetails तत्व से बाध्य रखें, और इसे कभी भी हटाएं। फिर जब आपके NameView में क्लिक ईवेंट होता है, तो इसका मॉडल ट्रिगर एक ईवेंट ट्रिगर करता है। फिर आपके SportsManDetailsView इसी संग्रह में ईवेंट को सुन सकते हैं और तदनुसार स्वयं को पुनः प्रस्तुत कर सकते हैं। बैकबोन की घटनाओं को गले लगाओ! जावास्क्रिप्ट एक घटना-संचालित भाषा है, और कभी नहीं भूलें कि आपके पास तोपखाने में हैं।

मैंने आपके JSFiddle को अपडेट किया है ताकि मैंने कुछ लोगों के बारे में बात की हो।

+0

यह वास्तव में है कमाल! तुमने मुझे इस मामले पर प्रबुद्ध किया। बहुत बहुत धन्यवाद – Buzut

+0

कोई समस्या नहीं! आपने एक अच्छा सवाल पूछा है कि एक अच्छी व्याख्या के लिए। आपकी रीढ़ की हड्डी पर शुभकामनाएं! – ncksllvn

+0

मुझे नहीं लगता कि यह दोषपूर्ण होगा, लेकिन यह इसका हिस्सा है खेल। फिर से धन्यवाद :) – Buzut

0
el: '#sportsManDetails', 

अगर आप बार जब आप को देखने के एक निर्माता बनाने पर jQuery लोड नहीं काम न करें।

सुनिश्चित करें कि आप jQuery इस लाइन से पहले लोड

app.SportsManDetailsView = Backbone.View.extend({ 

आप

console.log(jQuery.fn.jquery);` 
+0

और फिर भी, 'console.log (jQuery.fn.jquery) जोड़ना; 'ऐप से ठीक पहले .portsManDetailsView = Backbone.View.extend ({' आउटपुट 2.1.1, jQuery को प्रमाणित करना अच्छी तरह से लोड हो गया है ... – Buzut

संबंधित मुद्दे