2010-01-14 17 views
9

मैं अभी कुछ समय के लिए jQuery प्लगइन्स विकसित कर रहा हूं, और मुझे लगता है कि मुझे पता है कि अब तक मुझे एक अच्छी तरह से डिज़ाइन करना है। एक मुद्दा मुझे परेशान करता रहता है, और यह एक शक्तिशाली लेकिन सुरुचिपूर्ण तरीके से निजी कार्यों से निपटने का तरीका है।jQuery प्लगइन डिज़ाइन पैटर्न (सामान्य अभ्यास?)

(function($) { 

    $.fn.myplugin = function(...) { 
    ... 
    // some shared functionality, for example: 
    this.css('background-color', 'green'); 
    ... 
    }; 
    $.fn.mypluginAnotherPublicMethod = function(...) { 
    ... 
    // some shared functionality, for example: 
    this.css('background-color', 'red'); 
    ... 
    }; 

}(jQuery)); 

अब मेरे सवाल है: कैसे बड़े करीने से ऊपर साझा कार्यक्षमता सुखाने के लिए

मेरे प्लगइन्स आम तौर पर कुछ इस तरह दिखाई? एक स्पष्ट समाधान प्लगइन का नाम स्थान के भीतर एक समारोह में यह डाल करने के लिए होगा:

var fill = function($obj, color) { 
    $obj.css('background-color', color); 
}; 

हालांकि यह समाधान प्रभावी और अच्छी तरह से namespaced है, मैं वास्तव में यह पसंद नहीं। एक साधारण कारण के लिए: मुझे इसे jQuery ऑब्जेक्ट पास करना होगा। अर्थात। जबकि मैं इसे इस तरह कॉल करना चाहते हैं, fill(this, 'red');: this.fill('red');

बेशक

हम बस jQuery.fn में fill डालकर इस परिणाम प्राप्त कर सकता है मैं इसे इस तरह कॉल करने के लिए की है। लेकिन यह बहुत असहज महसूस करता है। कल्पना करें कि इस दृष्टिकोण के आधार पर दस प्लगइन्स विकसित किए गए हैं और प्रत्येक प्लगइन ने उन पांच निजी 'फ़ंक्शंस को jQuery फ़ंक्शन नेमस्पेस में डाला है। यह एक बड़ी गड़बड़ी में समाप्त होता है। हम इन कार्यों में से प्रत्येक को प्लगइन के नाम से उपसर्ग करके कम कर सकते हैं, लेकिन इससे वास्तव में यह अधिक आकर्षक नहीं होता है। इन कार्यों को प्लगइन के लिए निजी माना जाता है, इसलिए हम उन्हें बाहरी दुनिया में कम से कम नहीं दिखाना चाहते हैं (कम से कम सीधे नहीं)।

तो मेरा प्रश्न है: क्या आप में से कोई भी सुझाव है कि दोनों दुनिया के सर्वश्रेष्ठ कैसे प्राप्त करें। अर्थात्; प्लगइन कोड 'निजी' प्लगइन फ़ंक्शन को this.fill('red') (या this.myplugin.fill('red') या यहां तक ​​कि this.myplugin().fill('red') इत्यादि) के समान तरीके से कॉल करने में सक्षम होने के कारण, jQuery फ़ंक्शन नेमस्पेस प्रदूषण को रोकने के दौरान। और निश्चित रूप से यह हल्के वजन होना चाहिए, क्योंकि इन निजी कार्यों को अक्सर बार कहा जा सकता है।


अद्यतन: अपने सुझाव के लिए धन्यवाद।

मुझे विशेष रूप से डेविड के एक ऑब्जेक्ट प्रकार को परिभाषित करने का विचार पसंद है जिसमें 'निजी' फ़ंक्शन हैं और एक jQuery ऑब्जेक्ट लपेटता है। इसके साथ एकमात्र समस्या यह है कि यह मुझे अभी भी 'निजी' और 'सार्वजनिक' कार्यों को चुनने से रोकता है। शुरू करने के लिए this.fill('red') जैसे सिंटैक्स को प्राप्त करने का एक बड़ा कारण था।

मैं एक समाधान है जो मुझे काफी सुंदर नहीं पर विचार के साथ समाप्त हो गया है, लेकिन कारण 'दोनों दुनिया के सर्वश्रेष्ठ' को अपील:

$.fn.chain = function(func) { 
    return func.apply(this, Array.prototype.slice.call(arguments, 1)); 
}; 

कौन सा तरह निर्माणों के लिए अनुमति देता है:

this. 
    find('.acertainclass'). 
    chain(fill, 'red'). 
    click(function() { 
     alert("I'm red"); 
    }); 

मैं अन्य स्थानों पर मेरा प्रश्न पार कर गया, जिसने कुछ रोचक प्रतिक्रियाएं भी एकत्र की:

उत्तर

2

कैसे के बारे में (प्लगइन के दायरे के भीतर):

var fill = function() 
{ 
    (function (color) 
    { 
     this.css ('backgrorund-color', color); 
     //.. your stuff here ... 
    }).apply (this, arguments); 
} 

$.fn.myplugin = function() 
{ 
    fill ('green'); 
} 

इस तरह, भरने jQuery संदर्भ में लिप्त हों बनी रहेगी, और अभी भी अपने प्लगइन के लिए निजी है


संशोधित: उपरोक्त गलत wrt है scoping, निम्नलिखित बजाय का प्रयास करें:

var fill = function (color) 
{ 
    if (!$this) return; // break if not within correct context 

    $this.css ('backgrorund-color', color); 
    //.. your stuff here ... 
} 

$.fn.myplugin = function() 
{ 
    var $this = $(this); // local ref to current context 
    fill ('green'); 
} 
+1

तो कैसे भरने करता है() $ .fn.myplugin() से करने के लिए 'इस' पर पकड़? –

+0

'यह' नहीं होगा (फ़ंक्शन (रंग) {...}) 'फ़ंक्शन? – nickf

+0

मुझे लगता है कि ये इस कोड नमूने में 'इस' हैं: (1) '$ obj.myplugin()': $ obj' (2) 'भरें() ':' विंडो' (3) 'फ़ंक्शन (रंग)': 'विंडो' –

0

दुर्भाग्य से, "निजी" तरीकों (या उस बात के लिए किसी भी संपत्ति) कभी नहीं जावास्क्रिप्ट में एक "इस" उपसर्ग के साथ कहा जा सकता है। this.myFunc(myArgs) जैसे किसी भी चीज को सार्वजनिक रूप से उपलब्ध होना चाहिए।

और "निजी" विधियों को केवल उस क्षेत्र के भीतर से ही बुलाया जा सकता है जिसमें उन्हें परिभाषित किया गया था।

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

this.fill('green'); 
//or 
fill(this,'green'); 

आप देख सकते हैं, वे दोनों में वर्णों की बिल्कुल एक ही नंबर का समय लग तुम्हारा कोड।

कहने के लिए खेद है, लेकिन आप इसे एक समाधान के रूप में फंस गए हैं, जब तक कि आप एक नया नामस्थान नहीं बनाना चाहते हैं और उन्हें निजी नहीं बनाएं - जो आपको लिखने के लिए आवश्यक कोड की मात्रा में जोड़ने जा रहा है अर्थात क्या आप अप्रत्यक्ष रूप से बुलाया "सीधे संपर्क में नहीं":

this.myplugin.fill('green'); 

... और वर्बोज़, इस प्रकार एक तरह से उद्देश्य धरा है।

जावास्क्रिप्ट अन्य भाषाओं की तरह नहीं है, वहां कोई "निजी" सदस्य प्रति-सी नहीं हैं, केवल सदस्यों को बंद करने के भीतर सुलभ किया जा सकता है, जिन्हें कभी-कभी निजी सदस्यों के समान तरीके से उपयोग किया जा सकता है, लेकिन यह "कामकाज" से अधिक है, और न कि "असली सौदा" निजी सदस्य जिन्हें आप ढूंढ रहे हैं।

यह इस शर्तों के साथ संबंध के लिए (मैं अक्सर संघर्ष) मुश्किल हो सकता है, लेकिन नहीं है कि तुम क्या अन्य भाषाओं से समझ में में जावास्क्रिप्ट मोल्ड करने के लिए, यह क्या है के लिए इसे ले कोशिश ...

11

एक बात पहले: यदि आप this.fill('red'); की तरह कुछ कॉल करने के लिए जहां इस jQuery का एक उदाहरण है चाहते हैं, तो आप jQuery प्रोटोटाइप का विस्तार करने और fill() "सार्वजनिक" बनाने के लिए किया है। jQuery तथाकथित "प्लगइन्स" का उपयोग करके इसके प्रोटोटाइप को विस्तारित करने के लिए दिशानिर्देश प्रदान करता है जिसे $.fn.fill का उपयोग करके जोड़ा जा सकता है, जो jQuery.prototype.fill जैसा ही है।

jQuery कॉलबैक में, यह अक्सर HTML तत्व का संदर्भ है, और आप उन (अभी तक) प्रोटोटाइप नहीं जोड़ सकते हैं। यही कारण है कि jQuery तत्वों को लपेटता है और jQuery उदाहरण लौटाता है जिसे आसानी से बढ़ाया जा सकता है।

(function(){})(); सिंटैक्स का उपयोग करके, आप फ्लाई पर "निजी" जावास्क्रिप्ट बना और निष्पादित कर सकते हैं, और यह सब खत्म होने पर गायब हो जाता है। इस तकनीक का उपयोग करके, आप अपना स्वयं का jQuery-जैसा वाक्यविन्यास बना सकते हैं जो jQuery को आपकी निजी श्रृंखला योग्य वस्तु में लपेटता है।

(function(){ 
    var P = function(elem) { 
     return new Private(elem); 
    }; 
    var Private = function(elem) { 
     this.elem = jQuery(elem); 
    } 
    Private.prototype = { 
     elem: null, 
     fill: function(col) { 
      this.elem.css('background',col); 
      return this; 
     }, 
     color: function(col) { 
      this.elem.css('color', col); 
      return this; 
     } 
    } 

    $.fn.myplugin = function() { 
     P(this).fill('red'); 
    }; 
    $.fn.myotherplugin = function() { 
     P(this).fill('yellow').color('green'); 
    }; 

})(); 

$('.foo').myplugin(); 
$('.bar').myotherplugin(); 

console.log(typeof P === 'undefined') // should print 'true' 

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

2

आप यह देखना चाहते हैं कि jQuery UI Widget Factory लागू किया गया है।

बुनियादी दृष्टिकोण इस तरह है:

(function($){ 
    $.fn.myplugin = function(method) 
    { 
     if (mp[method]) // map $('foo').myplugin('bar', 'baz') to mp.bar('baz') 
     { 
      return mp[method].apply(this, Array.prototype.slice.call(arguments, 1)); 
     } 
     else if (typeof method === 'object' || ! method) 
     { 
      return mp.init.apply(this, arguments); // if called without arguments, init 
     } 
     else 
     { 
      $.error('Method ' + method + ' does not exist on $.myplugin'); 
     } 
    }; 

    // private methods, internally accessible via this.foo, this.bar 
    var foo = function() { … }; 
    var bar = function() { … }; 

    var private = { // alternative approach to private methods, accessible via this.private.foo 
     foo : function() { … }, 
     bar : function() { … } 
    } 

    var mp = { // public methods, externally accessible via $.myplugin('foo', 'bar') 
     init : function(options) 
     { 
      return this.each(function() 
      { 
       // do init stuff 
      } 
     }, 
     foo : function() { … }, 
     bar : function() { … } 
    }; 
})(jQuery); 
+0

आप एक वैरिएबल नाम के लिए 'निजी' के अलावा अन्य उपयोग करना चाहते हैं, क्योंकि यह ईसीएमएस्क्रिप्ट – jinglesthula

+0

@jinglesthula में एक आरक्षित (भविष्य के उपयोग के लिए) शब्द है, अच्छा पकड़, धन्यवाद! – vzwick

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