2013-08-09 6 views
6

के बीच परिपत्र निर्भरता मैं मौजूदा वर्किंग कोड बेस लेने और जावास्क्रिप्ट का उपयोग करके ऑब्जेक्ट उन्मुख बनाने की कोशिश कर रहा हूं। मेरी प्रणाली में एक से अधिक रिश्तों में समूह और आइटम युक्त JSON लेता है, और इसे किसी पृष्ठ पर विज़ुअलाइज़ करता है। वस्तुओं को विभिन्न समूहों में स्थानांतरित किया जा सकता है, और उन समूहों के भीतर उनकी स्थिति को भी गणना करने की आवश्यकता है। इस प्रकार, घटनाओं को स्थापित करने की आवश्यकता होगी जो उनके आसपास के समूहों और टिकट दोनों से अवगत हैं।जावास्क्रिप्ट क्लास और jQuery ऑब्जेक्ट

मैं दो कक्षाओं, Item और Group स्थापित करने के लिए John Resig's सरल जावास्क्रिप्ट विरासत सेटअप का उपयोग कर रहा हूं। जब प्रत्येक Item तत्काल होता है तो यह उसके माता-पिता Group पर वापस संदर्भित करता है। मेरे मुद्दा उठता है जब मैं अपने घटनाओं स्थापित करना चाहते हैं, और सबसे आसानी से निम्नलिखित समारोह द्वारा समझाया गया है:

var Group = Class.extend({ 
    ... 
    // Calculate where to place the new item within the group 
    calculate_new_position: function(item) { 
    var pos = -1; 
    // Loop through all DOM items in groups body 
    $(".item", this.elBody).each(function(i) { 

     // Retrieve it's class object 
     var next = $(this).data("_obj"); 

     // Calculating things using the class reference 
     var lowerPrio = item.tData.priority < next.tData.priority, 
      lowerId = item.id < next.id; 

     if(lowerPrio || lowerId) { 
     pos = i; 
     return false; 
     } 
    }); 
    return pos; 
    }, 
    ... 
)}; 

नोट ऊपर स्निपेट में .data("_obj") का उपयोग। अनिवार्य रूप से, जब मुझे वस्तुओं को सॉर्ट करने की तरह कुछ करने की आवश्यकता होती है, तो मुझे समूह में प्रत्येक आइटम के डोम (व्यू/कंट्रोलर) से संबंधित वस्तु (मॉडल) को जानने की आवश्यकता होती है। अब, मैं अपना Group कक्षा स्थापित कर सकता हूं ताकि जब मैं प्रत्येक Item बनाउंगा, तो मैं इसे Group (उदा। Group.items = [i1, i2...]) के भीतर से संदर्भित करता हूं, और फिर डीओएम तत्वों को फिर से चालू करने के बजाय, मैं Item उदाहरणों पर फिर से चला सकता हूं। हालांकि मुझे लगता है कि मैं लाइन के नीचे समान समस्याओं में भाग लेगा, जैसे कि जब मैं Item को एक अलग Group में स्थानांतरित करना चाहता हूं (GroupItem के बारे में नहीं पता होगा)।

लंबी कहानी कम: यह आंतरिक रूप से खतरनाक/भोली/व्यर्थ एक वर्ग है जो जब instantiated एक डोम तत्व बनाता है, है जो तब बारी अंक वापस वर्ग के लिए में? यह परिपत्र निर्भरता, और कुछ पुनरावर्ती दुःस्वप्न की तरह लगता है, लेकिन शायद किसी वस्तु का संदर्भ ऐसी भयानक बात नहीं है। अगर मैं कुछ और कर रहा हूं वास्तव में बेवकूफ, और एक बहुत ही आसान तरीका है, तो कृपया इसे भी इंगित करें।

+0

क्या आपने देखा है कि Backbone.js कैसे करता है? एक 'व्यू' ऑब्जेक्ट में 'मॉडल' (आपकी वस्तु, समूह श्रेणी) और डीओएम तत्व 'el' का संदर्भ होता है। इसे करने और बैकबोन करने के कई तरीके हैं।जेएस यहां किसी भी तरह की सिफारिश नहीं करता है: http://backbonejs.org/#FAQ-tim-toady – vsr

उत्तर

2

कोई भी आधुनिक ब्राउज़र कचरा कलेक्टर परिपत्र संदर्भों को संभाल सकता है। यदि आप दोनों ऑब्जेक्ट के सभी संदर्भ खो देते हैं और डीओएम से सभी HTML नोड्स को हटाते हैं तो आपके ऑब्जेक्ट को कचरा इकट्ठा किया जाएगा (जबकि डोम में ब्राउज़र आपके ऑब्जेक्ट का संदर्भ देखेगा और इसे कचरा होने से रोक देगा)। हालांकि ईवेंट हैंडलर से सावधान रहें, अगर आप उन्हें भी नहीं हटाते हैं तो वे रिफेंस रख सकते हैं।

मैंने सुना है कि आईई के कुछ पुराने संस्करणों में परिपत्र संदर्भों में समस्या है। Precise explanation of JavaScript <-> DOM circular reference issue

है कि इसका जवाब है: द्वारा: depht विवरण में अधिक जानकारी के लिए jQuery के .data() बात और अधिक विश्वसनीय बनाता है क्योंकि IE के पुराने संस्करणों है कि एक डोम तत्व को जोड़ा गया था और परिपत्र संभाल नहीं किया गुणों के साथ एक विशेष समस्या नहीं थी संदर्भ उन गुणों में डेटा को सही ढंग से शामिल करते हैं और इस प्रकार चीजों को मुक्त नहीं करेंगे जब यह होना चाहिए (एक रिसाव)। .data() डीओएम तत्व पर केवल एक अतिरिक्त संपत्ति का उपयोग करके उसमें काम करता है जो एक सुरक्षित, गैर-लीकिंग स्ट्रिंग है। वह स्ट्रिंग तब जावास्क्रिप्ट ऑब्जेक्ट में एक कुंजी है जिसमें सभी गुण हो सकते हैं जिन्हें आप DOM तत्व से जोड़ना चाहते हैं। चूंकि ये गुण सादे जावास्क्रिप्ट में सभी स्टोर हैं, जहां ब्राउज़र में परिपत्र संदर्भ बग नहीं होते हैं, इस तरह से ऐसा करने से लीक नहीं होती है।

आप शायद D3.js में देखना चाहते हैं, यह आपके जैसा कुछ भी करता है।यह डोम तत्वों को डेटा बांधता है और आसान तरीका दृश्यावलोकन उत्पन्न करने के लिए प्रदान करता है: http://d3js.org/

डी 3 का उपयोग करके आप चक्र एसवीजी टैग की एक सरणी के लिए संख्या की एक सरणी के लिए बाध्य है और यह इसलिए प्रत्येक चक्र संख्या के आधार पर एक त्रिज्या है कि कर सकते हैं इसके साथ जुड़े सरणी के।

संपादित करें: मैं यह उल्लेख करना भूल गया कि यदि आप $ .remove() का उपयोग करते हैं तो ईवेंट हैंडलर भी हटा दिए जाते हैं। लेकिन अगर आपके पास उदाहरण के लिए एक ईवेंट हैंडलर है जो बंद होने के अंदर है जिसमें आपके (हटाए गए) HTML नोड का भी संदर्भ है, तो यह कचरा नहीं होगा। यह आम तौर पर एक बड़ी समस्या नहीं है क्योंकि एक बार जब यह डोम के बाहर होता है तो यह बहुत अधिक संसाधनों का उपभोग नहीं करेगा और जहां तक ​​मुझे पता है, उन बंद संदर्भों को दोबारा शुरू करना संभव नहीं है।

1

jQuery.data का उपयोग करते समय यह डोम तत्व के साथ कुछ भी नहीं करता है। डोम तत्व बस jQuery आंतरिक कैश में एक आदिम कुंजी प्रविष्टि स्टोर करता है, परवाह किए बिना *। संदर्भ आप इसलिए बनाने जे एस से जे एस के लिए है:

var div = document.createElement("div"); 
$(div).data("asd", "daa") 
console.log(div[jQuery.expando]); 
//41 
console.log(jQuery.cache[41].data.asd); 
//"daa" 

(जाहिर है इसके बाद के संस्करण jQuery internals है और उत्पादन कोड में पर भरोसा नहीं किया जाना चाहिए)

जिसके अनुसार, डेटा वहाँ अगर रिसाव हो जाएगा आप अपने सभी मैनिप्लेशंस करने के लिए jQuery से नहीं जाते हैं क्योंकि यदि आप इसके पीछे पीछे जाते हैं तो jQuery को अधिसूचित नहीं किया जाएगा।

विजेट कक्षाओं के साथ सबसे अच्छा अभ्यास destroy विधि प्रदान करना है जो सभी तत्वों को हटा देता है, जो इसे किसी भी घटना से जोड़ता है और इसके सभी डोम संदर्भों को शून्य में सेट करता है।

* यदि तत्व के बारे में बिल्कुल कोई घटना या डेटा नहीं है, तो एक प्रविष्टि मौजूद नहीं है। लेकिन अगर किसी भी कारण से कोई प्रविष्टि मौजूद है, तो jQuery.data का उपयोग तत्व के साथ ही बातचीत नहीं करेगा।

1

@ हॉफमैन का जवाब अच्छा है क्योंकि वह स्पष्टीकरण के साथ व्यावहारिक सलाह दे रहा है। मैं बैकबोन.जेएस कैसे काम करता है इससे प्रेरित एक अलग परिप्रेक्ष्य प्रदान करता हूं। यह @Vsr ने अपनी प्रारंभिक टिप्पणी में सुझाव दिया है कि यह एक विस्तार है।

मूल जोर: अपने जेएस ऑब्जेक्ट्स को $ .data() में स्टोर न करें।

$ .data() आप $ (foo) का उपयोग डोम वस्तुओं को देखने के लिए तो उनके गुणों में अंदर घुसते अपने कस्टम जेएस कार्यों को पाने के लिए, और अधिक DOM तत्वों पर काम हो सकता है उनके पर प्राप्त करने के लिए पता चलता है का उपयोग करना कस्टम फ़ंक्शन यह अत्यधिक जटिल और अक्षम है।

जो भी वाक्यविन्यास और तंत्र आपकी आवश्यकताओं के अनुरूप है, का उपयोग करके "शुद्ध जेएस" ऑब्जेक्ट्स का एक सेट बनाने का एक बेहतर तरीका है। इन वस्तुओं में तब एक संपत्ति हो सकती है जो उन कुछ अवसरों के लिए उनके डीओएम तत्व को इंगित करती है जहां इसकी आवश्यकता होती है। बैकबोन (फिर से) jQuery चयनित डीओएम तत्व को कैश करने के लिए भी अच्छा अभ्यास सुझाता है। इन "शुद्ध जेएस" ऑब्जेक्ट्स को प्रोसेस करना $ .data() के माध्यम से जाने से पहले बनाए रखने के लिए तेज़ और आसान होगा। यह आपके जेएस और एचटीएमएल के बीच अमूर्तता को भी बढ़ाता है, जो एक अच्छी बात है।

आगे, मुझे काम करने का एक अच्छा तरीका मिल गया है, यह आपके ऑब्जेक्ट्स को घोंसला नहीं देना है, भले ही केवल एक-से-कई संबंध हों। "समूह" के "आइटम" गुण न बनाएं। इसके बजाय, दोनों समूहों और वस्तुओं के सरणी बनाए रखें और एक (या दोनों) सदस्यता के बजाय संदर्भ द्वारा एसोसिएशन का प्रबंधन करें।

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