angularjs - कोणीय निर्देश-संकलन, नियंत्रक, प्री-लिंक और पोस्ट-लिंक का उपयोग कब और कैसे करें




angularjs-directive (6)

इन फ़ंक्शन कॉल के बीच और क्या होता है?

विभिन्न निर्देश कार्यों को दो अन्य कोणीय कार्यों के भीतर से निष्पादित किया जाता है जिन्हें $compile कहा जाता है (जहां निर्देश का compile निष्पादित किया जाता है) और nodeLinkFn नामक एक आंतरिक फ़ंक्शन (जहां निर्देशक controller , preLink और postLink निष्पादित होते हैं)। निर्देश कार्यों के पहले और बाद में कोणीय कार्य के भीतर कई चीजें होती हैं। शायद सबसे विशेष रूप से बाल रिकर्सन है। निम्नलिखित सरलीकृत चित्रण संकलन और लिंक चरणों के भीतर महत्वपूर्ण कदम दिखाता है:

इन चरणों का प्रदर्शन करने के लिए, निम्न HTML मार्कअप का उपयोग करें:

<div ng-repeat="i in [0,1,2]">
    <my-element>
        <div>Inner content</div>
    </my-element>
</div>

निम्नलिखित निर्देश के साथ:

myApp.directive( 'myElement', function() {
    return {
        restrict:   'EA',
        transclude: true,
        template:   '<div>{{label}}<div ng-transclude></div></div>'
    }
});

संकलित करें

compile एपीआई इस तरह दिखता है:

compile: function compile( tElement, tAttributes ) { ... }

अक्सर पैरामीटर तत्वों को इंगित करने के लिए t साथ prefixed हैं और प्रदान किए गए गुण उदाहरण के बजाए स्रोत टेम्पलेट के हैं।

स्थानांतरित सामग्री को compile करने के लिए कॉल से पहले (यदि कोई है) हटा दिया गया है, और टेम्पलेट मार्कअप पर लागू होता है। इस प्रकार, compile समारोह में प्रदान किया गया तत्व इस तरह दिखेगा:

<my-element>
    <div>
        "{{label}}"
        <div ng-transclude></div>
    </div>
</my-element>

ध्यान दें कि इस बिंदु पर स्थानांतरित सामग्री को फिर से सम्मिलित नहीं किया गया है।

निर्देश के लिए कॉल के बाद। .compile , कोणीय सभी बाल तत्वों को पार करेगा, जिनमें निर्देशों द्वारा प्रस्तुत किया गया हो सकता है (उदाहरण के लिए टेम्पलेट तत्व)।

इंस्टेंस निर्माण

हमारे मामले में, उपरोक्त स्रोत टेम्पलेट के तीन उदाहरण बनाए जाएंगे ( ng-repeat द्वारा)। इस प्रकार, प्रति उदाहरण एक बार, निम्नलिखित अनुक्रम तीन बार निष्पादित होगा।

नियंत्रक

controller एपीआई में शामिल हैं:

controller: function( $scope, $element, $attrs, $transclude ) { ... }

लिंक चरण दर्ज करना, $compile माध्यम से लौटा लिंक लिंक अब एक दायरे के साथ प्रदान किया जाता है।

सबसे पहले, लिंक फ़ंक्शन अनुरोध किए जाने पर एक बच्चे का दायरा ( scope: true ) या एक अलग दायरा ( scope: {...} ) बनाता है।

तब नियंत्रक को निष्पादित किया जाता है, उदाहरण के तत्व के दायरे के साथ प्रदान किया जाता है।

पूर्व लिंक

pre-link एपीआई ऐसा दिखता है:

function preLink( scope, element, attributes, controller ) { ... }

निर्देश के लिए कॉल के बीच वस्तुतः कुछ भी नहीं होता है। .controller और .preLink फ़ंक्शन। कोणीय अभी भी सिफारिश प्रदान करता है कि प्रत्येक को कैसे उपयोग किया जाना चाहिए।

.preLink कॉल के बाद, लिंक फ़ंक्शन प्रत्येक बच्चे तत्व को पार करेगा - सही लिंक फ़ंक्शन को कॉल करेगा और इसे वर्तमान दायरे से जोड़ देगा (जो बाल तत्वों के लिए मूल दायरे के रूप में कार्य करता है)।

पोस्ट-लिंक

post-link एपीआई pre-link फ़ंक्शन के समान है:

function postLink( scope, element, attributes, controller ) { ... }

शायद यह ध्यान देने योग्य है कि निर्देश के बाद। .postLink फ़ंक्शन कहा जाता है, अपने बच्चों के सभी तत्वों की लिंक प्रक्रिया पूरी हो गई है, जिसमें सभी बच्चों के। .postLink फ़ंक्शन शामिल हैं।

इसका मतलब है कि उस समय तक। .postLink कहा जाता है, बच्चे 'लाइव' तैयार हैं। यह भी शामिल है:

  • अनिवार्य तथ्य
  • हस्तांतरण लागू
  • गुंजाइश संलग्न

इस चरण में टेम्पलेट इस तरह दिखता है:

<my-element>
    <div class="ng-binding">
        "{{label}}"
        <div ng-transclude>                
            <div class="ng-scope">Inner content</div>
        </div>
    </div>
</my-element>

एक कोणीय निर्देश लिखते समय, कोई भी निम्नलिखित कार्यों में से किसी एक का उपयोग कर सकता है ताकि डोम व्यवहार, सामग्री और उस तत्व को देख सकें जिस पर निर्देश घोषित किया गया है:

  • संकलन
  • नियंत्रक
  • पूर्व लिंक
  • बाद लिंक

ऐसा कुछ भ्रम प्रतीत होता है क्योंकि किस फ़ंक्शन को उपयोग करना चाहिए। इस सवाल में शामिल हैं:

निर्देश मूल बातें

  • विभिन्न कार्यों की घोषणा कैसे करें?
  • स्रोत टेम्पलेट और एक उदाहरण टेम्पलेट के बीच क्या अंतर है?
  • किस क्रम में निर्देश कार्यों को निष्पादित किया जाता है?
  • इन फ़ंक्शन कॉल के बीच और क्या होता है?

फंक्शन प्रकृति, क्या करें और न करें

  • Compile
  • Controller
  • Pre-link
  • Post-link

संबंधित सवाल:


किस क्रम में निर्देश कार्यों को निष्पादित किया जाता है?

एक ही निर्देश के लिए

निम्नलिखित plunk आधार पर, निम्न HTML मार्कअप पर विचार करें:

<body>
    <div log='some-div'></div>
</body>

निम्नलिखित निर्देश घोषणा के साथ:

myApp.directive('log', function() {

    return {
        controller: function( $scope, $element, $attrs, $transclude ) {
            console.log( $attrs.log + ' (controller)' );
        },
        compile: function compile( tElement, tAttributes ) {
            console.log( tAttributes.log + ' (compile)'  );
            return {
                pre: function preLink( scope, element, attributes ) {
                    console.log( attributes.log + ' (pre-link)'  );
                },
                post: function postLink( scope, element, attributes ) {
                    console.log( attributes.log + ' (post-link)'  );
                }
            };
         }
     };  

});

कंसोल आउटपुट होगा:

some-div (compile)
some-div (controller)
some-div (pre-link)
some-div (post-link)

हम देख सकते हैं कि compile पहले निष्पादित किया गया है, फिर controller , फिर pre-link और आखिरी post-link

नेस्टेड निर्देशों के लिए

नोट: निम्नलिखित उन निर्देशों पर लागू नहीं होता है जो अपने बच्चों को उनके लिंक फ़ंक्शन में प्रस्तुत करते हैं। काफी कुछ कोणीय निर्देश ऐसा करते हैं (जैसे ngIf, ngRepeat, या transclude साथ कोई निर्देश)। इन निर्देशों के मूल रूप से उनके link फ़ंक्शन को उनके बच्चे निर्देशों के compile से पहले बुलाया जाएगा।

मूल HTML मार्कअप अक्सर नेस्टेड तत्वों से बना होता है, प्रत्येक के अपने निर्देश के साथ। निम्नलिखित मार्कअप की तरह ( plunk देखें):

<body>
    <div log='parent'>
        <div log='..first-child'></div>
        <div log='..second-child'></div>
    </div>
</body>

कंसोल आउटपुट इस तरह दिखेगा:

// The compile phase
parent (compile)
..first-child (compile)
..second-child (compile)

// The link phase   
parent (controller)
parent (pre-link)
..first-child (controller)
..first-child (pre-link)
..first-child (post-link)
..second-child (controller)
..second-child (pre-link)
..second-child (post-link)
parent (post-link)

हम यहां दो चरणों को अलग कर सकते हैं - संकलन चरण और लिंक चरण।

संकलन चरण

जब डोम लोड होता है तो कोणीय संकलन चरण शुरू करता है, जहां यह मार्कअप टॉप-डाउन को पार करता है, और सभी निर्देशों पर compile करता है। ग्राफिकल रूप से, हम इसे इस तरह व्यक्त कर सकते हैं:

यह उल्लेख करना शायद महत्वपूर्ण है कि इस चरण में, संकलित फ़ंक्शन टेम्पलेट्स स्रोत टेम्पलेट्स (उदाहरण टेम्पलेट नहीं) हैं।

लिंक चरण

डीओएम उदाहरण अक्सर डीओएम को प्रस्तुत किए जाने वाले स्रोत टेम्पलेट का परिणाम होते हैं, लेकिन उन्हें ng-repeat या फ्लाई पर पेश किया जा सकता है।

जब भी निर्देश के साथ एक तत्व का एक नया उदाहरण डीओएम को प्रदान किया जाता है, लिंक चरण शुरू होता है।

इस चरण में, कोणीय controller , pre-link , बच्चों को पुन: सक्रिय करता है, और सभी निर्देशों पर post-link कॉल करता है, जैसे:


पोस्ट-लिंक फ़ंक्शन

जब post-link फ़ंक्शन कहा जाता है, तो पिछले सभी कदम उठाए गए हैं - बाइंडिंग, ट्रांसक्यूलेशन इत्यादि।

यह आम तौर पर प्रस्तुत डीओएम में हेरफेर करने के लिए एक जगह है।

कर:

  • डीओएम (rendered, और इस प्रकार तत्काल) तत्वों का उपयोग करें।
  • घटना हैंडलर संलग्न करें।
  • बाल तत्वों का निरीक्षण करें।
  • विशेषताओं पर अवलोकन सेट करें।
  • दायरे पर घड़ियों सेट करें।

प्री-लिंक फ़ंक्शन

जब भी कोई नया संबंधित तत्व तत्काल होता है तो प्रत्येक निर्देश का pre-link फ़ंक्शन कहा जाता है।

जैसा कि संकलन आदेश खंड में पहले देखा गया था, pre-link फ़ंक्शंस को पैरेंट-अप-चाइल्ड कहा जाता है, जबकि post-link फ़ंक्शंस को child-then-parent कहा जाता है।

pre-link फ़ंक्शन का शायद ही कभी उपयोग किया जाता है, लेकिन विशेष परिदृश्यों में उपयोगी हो सकता है; उदाहरण के लिए, जब कोई बच्चा नियंत्रक अपने आप को मूल नियंत्रक के साथ पंजीकृत करता है, लेकिन पंजीकरण parent-then-child फैशन में होना चाहिए ( ngModelController इस तरह से काम करता है)।

ऐसा न करें:

  • बाल तत्वों का निरीक्षण करें (वे अभी तक प्रस्तुत नहीं किए जा सकते हैं, दायरे से बंधे हैं, इत्यादि)।

संकलन समारोह

प्रत्येक निर्देश का compile फ़ंक्शन केवल एक बार कहा जाता है, जब कोणीय बूटस्ट्रैप्स।

आधिकारिक तौर पर, यह (स्रोत) टेम्पलेट मैनिप्लेशंस करने का स्थान है जिसमें स्कोप या डेटा बाइंडिंग शामिल नहीं है।

मुख्य रूप से, यह अनुकूलन उद्देश्यों के लिए किया जाता है; निम्नलिखित मार्कअप पर विचार करें:

<tr ng-repeat="raw in raws">
    <my-raw></my-raw>
</tr>

<my-raw> निर्देश डीओएम मार्कअप का एक विशेष सेट प्रस्तुत करेगा। तो हम या तो कर सकते हैं:

  • स्रोत टेम्पलेट ( <my-raw> ) को डुप्लिकेट करने के लिए ng-repeat को अनुमति दें, और फिर प्रत्येक इंस्टेंस टेम्पलेट के मार्कअप को संशोधित करें ( compile फ़ंक्शन के बाहर)।
  • वांछित मार्कअप ( compile फ़ंक्शन में) को शामिल करने के लिए स्रोत टेम्पलेट को संशोधित करें, और फिर इसे डुप्लिकेट करने के लिए ng-repeat को अनुमति दें।

यदि raws संग्रह में 1000 आइटम हैं, तो दूसरा विकल्प पहले की तुलना में तेज़ हो सकता है।

कर:

  • मार्कअप का उपयोग करें ताकि यह उदाहरण (क्लोन) के लिए टेम्पलेट के रूप में कार्य करता हो।

ऐसा न करें

  • घटना हैंडलर संलग्न करें।
  • बाल तत्वों का निरीक्षण करें।
  • विशेषताओं पर अवलोकन सेट करें।
  • दायरे पर घड़ियों सेट करें।

स्रोत टेम्पलेट और एक उदाहरण टेम्पलेट के बीच क्या अंतर है?

तथ्य यह है कि कोणीय डीओएम हेरफेर का मतलब है कि संकलन प्रक्रिया में इनपुट मार्कअप कभी-कभी आउटपुट से भिन्न होता है। विशेष रूप से, कुछ इनपुट मार्कअप को डीओएम में प्रस्तुत करने से पहले कुछ बार क्लोन किया जा सकता है (जैसे ng-repeat )।

कोणीय शब्दावली थोड़ा असंगत है, लेकिन यह अभी भी दो प्रकार के मार्कअप के बीच अंतर करता है:

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

निम्नलिखित मार्कअप यह दर्शाता है:

<div ng-repeat="i in [0,1,2]">
    <my-directive>{{i}}</my-directive>
</div>

स्रोत एचटीएमएल परिभाषित करता है

    <my-directive>{{i}}</my-directive>

जो स्रोत टेम्पलेट के रूप में कार्य करता है।

लेकिन चूंकि यह एक ng-repeat निर्देश के भीतर लपेटा गया है, इस स्रोत टेम्पलेट को क्लोन किया जाएगा (हमारे मामले में 3 बार)। ये क्लोन उदाहरण टेम्पलेट हैं, प्रत्येक डीओएम में दिखाई देगा और प्रासंगिक दायरे से बंधेगा।







angularjs-directive