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


451

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

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

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

प्रत्यक्ष मूल बातें

फंक्शन नेचर, डू एंड न

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


27
क्या है क्या ?
हैमिलिट

2
@ इयान देखें: ऑपरेटर ओवरलोडिंग । अनिवार्य रूप से यह सामुदायिक विकि के लिए है। संबंधित प्रश्नों के बहुत से उत्तर आंशिक हैं, पूरी तस्वीर नहीं दे रहे हैं।
इज़्हाकी

8
यह महान सामग्री है, लेकिन हम पूछते हैं कि यहां सब कुछ क्यू एंड ए प्रारूप के भीतर रखा जाना चाहिए। शायद आप इसे कई असतत प्रश्नों में तोड़ना चाहेंगे और फिर उन्हें टैग विकी से लिंक करेंगे?
फ्लेक्सो

57
भले ही यह पोस्ट ऑफ-टॉपिक और ब्लॉग-रूप में हो, लेकिन यह कोणीय निर्देशों की गहन व्याख्या प्रदान करने में सबसे उपयोगी था। कृपया इस पोस्ट को न हटाएं, प्रवेश!
Exegesis

12
ईमानदारी से, मैं मूल डॉक्स से भी परेशान नहीं हूं। एक स्टैकओवरफ़्लो पोस्ट या एक ब्लॉग आमतौर पर मुझे सेकंड के भीतर जाता है, मूल डॉक्स को समझने की कोशिश कर रहे मेरे बालों को फाड़ने के 15-30 मिनटों के बीच।
डेविड

जवाबों:


168

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

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

निम्नलिखित प्लंक के आधार पर , निम्नलिखित 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 मार्कअप अक्सर नेस्टेड तत्वों से बना होता है, प्रत्येक अपने स्वयं के निर्देश के साथ। निम्नलिखित मार्कअप की तरह ( प्लंक देखें ):

<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सभी निर्देशों पर कॉल करता है। आलेखीय रूप से, हम इसे इस तरह व्यक्त कर सकते हैं:

बच्चों के लिए संकलन लूप को दर्शाती एक छवि

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

लिंक चरण

DOM उदाहरण अक्सर एक स्रोत टेम्पलेट के DOM को दिए जाने का परिणाम होते हैं, लेकिन वे ng-repeatमक्खी द्वारा बनाए या बनाए जा सकते हैं।

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

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

लिंक चरण चरणों का प्रदर्शन करने वाला चित्रण


5
@lzhaki फ्लोचार्ट अच्छा लग रहा है। चार्टिंग टूल का नाम साझा करने का मन है? :)
मर्लिन

1
@merlin मैंने OmniGraffle का उपयोग किया है (लेकिन इलस्ट्रेटर या इंकस्केप का उपयोग किया जा सकता है - गति के अलावा, कुछ भी नहीं है OmniGraffle अन्य चार्टिंग टूल की तुलना में बेहतर है जहां तक ​​यह चित्रण है)।
इज़्हाकी

2
@ अनंत का प्लंकर गायब हो गया है इसलिए यहां एक नया: plnkr.co/edit/kZZks8HN0iFIY8ZaKJkA?p=preview लॉग इन स्टेटमेंट देखने के लिए JS कंसोल खोलें

क्यों यह सच नहीं है जब एनजी-रिपीट का उपयोग बच्चों के निर्देशों के लिए किया जाता है ??? प्लंक
Luckylooke

@Luckylooke आपके प्लंक को एनजी-रिपीट के तहत निर्देश के साथ कोई संतान नहीं मिली है (यानी, जो दोहराया जा रहा है वह एक निर्देश का एक टेम्पलेट है। यदि ऐसा होता है, तो आप देखेंगे कि उनका संकलन केवल एनजी-दोहराने के लिंक के बाद कहा जाता है।
इज़्हाकी

90

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

विभिन्न निर्देश कार्यों दो अन्य कोणीय कार्यों कहा जाता है के भीतर से क्रियान्वित कर रहे हैं $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दिया जाता है ताकि तत्वों और विशेषताओं को सूचित किया जा सके जो स्रोत टेम्पलेट के हैं, उदाहरण के बजाय।

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>

3
आपने यह ड्राइंग कैसे बनाई?
रॉय नमिर

6
@ रोयनिराम ओम्निग्राफेल।
इज़्हाकी

43

विभिन्न कार्यों की घोषणा कैसे करें?

संकलन, नियंत्रक, पूर्व-लिंक और पोस्ट-लिंक

यदि किसी को सभी चार फ़ंक्शन का उपयोग करना है, तो निर्देश इस फॉर्म का पालन करेगा:

myApp.directive( 'myDirective', function () {
    return {
        restrict: 'EA',
        controller: function( $scope, $element, $attrs, $transclude ) {
            // Controller code goes here.
        },
        compile: function compile( tElement, tAttributes, transcludeFn ) {
            // Compile code goes here.
            return {
                pre: function preLink( scope, element, attributes, controller, transcludeFn ) {
                    // Pre-link code goes here
                },
                post: function postLink( scope, element, attributes, controller, transcludeFn ) {
                    // Post-link code goes here
                }
            };
        }
    };  
});

ध्यान दें कि संकलन पूर्व-लिंक और पोस्ट-लिंक दोनों कार्यों से युक्त ऑब्जेक्ट को संकलित करता है; कोणीय लिंगो में हम कहते हैं कि संकलन फ़ंक्शन एक टेम्पलेट फ़ंक्शन देता है ।

संकलन, नियंत्रक और पोस्ट-लिंक

यदि pre-linkआवश्यक नहीं है, संकलित फ़ंक्शन केवल परिभाषा वस्तु के बजाय पोस्ट-लिंक फ़ंक्शन वापस कर सकता है, जैसे:

myApp.directive( 'myDirective', function () {
    return {
        restrict: 'EA',
        controller: function( $scope, $element, $attrs, $transclude ) {
            // Controller code goes here.
        },
        compile: function compile( tElement, tAttributes, transcludeFn ) {
            // Compile code goes here.
            return function postLink( scope, element, attributes, controller, transcludeFn ) {
                    // Post-link code goes here                 
            };
        }
    };  
});

कभी-कभी, एक compileविधि जोड़ने की इच्छा होती है , (पोस्ट) linkविधि परिभाषित होने के बाद । इसके लिए, कोई भी उपयोग कर सकता है:

myApp.directive( 'myDirective', function () {
    return {
        restrict: 'EA',
        controller: function( $scope, $element, $attrs, $transclude ) {
            // Controller code goes here.
        },
        compile: function compile( tElement, tAttributes, transcludeFn ) {
            // Compile code goes here.

            return this.link;
        },
        link: function( scope, element, attributes, controller, transcludeFn ) {
            // Post-link code goes here
        }

    };  
});

नियंत्रक और पोस्ट-लिंक

यदि कोई संकलन फ़ंक्शन की आवश्यकता नहीं है, तो कोई भी अपनी घोषणा को पूरी तरह से छोड़ सकता है और linkनिर्देश के कॉन्फ़िगरेशन ऑब्जेक्ट की संपत्ति के तहत लिंक-लिंक फ़ंक्शन प्रदान कर सकता है :

myApp.directive( 'myDirective', function () {
    return {
        restrict: 'EA',
        controller: function( $scope, $element, $attrs, $transclude ) {
            // Controller code goes here.
        },
        link: function postLink( scope, element, attributes, controller, transcludeFn ) {
                // Post-link code goes here                 
        },          
    };  
});

कोई नियंत्रक नहीं

ऊपर दिए गए किसी भी उदाहरण में, कोई केवल controllerफ़ंक्शन को हटा सकता है यदि आवश्यक नहीं है। उदाहरण के लिए, यदि केवल post-linkफ़ंक्शन की आवश्यकता है, तो कोई भी उपयोग कर सकता है:

myApp.directive( 'myDirective', function () {
    return {
        restrict: 'EA',
        link: function postLink( scope, element, attributes, controller, transcludeFn ) {
                // Post-link code goes here                 
        },          
    };  
});

31

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

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

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

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

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

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

स्रोत HTML परिभाषित करता है

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

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

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


23

संकलन समारोह

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

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

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

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

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

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

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

करना:

  • मार्कअप को मैनिप्युलेट करें ताकि यह इंस्टेंसेस (क्लोन) के टेम्पलेट के रूप में कार्य करे।

ऐसा न करें

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

20

नियंत्रक समारोह

controllerजब भी कोई नया संबंधित तत्व तात्कालिक होता है, तो प्रत्येक निर्देश के कार्य को कहा जाता है।

आधिकारिक तौर पर, controllerफ़ंक्शन वह है जहां एक:

  • नियंत्रक तर्क (विधियों) को परिभाषित करता है जो नियंत्रकों के बीच साझा किए जा सकते हैं।
  • कार्यक्षेत्र चर की शुरुआत करता है।

फिर, यह याद रखना महत्वपूर्ण है कि यदि निर्देश में एक अलग-अलग गुंजाइश शामिल है, तो इसके भीतर कोई भी गुण जो मूल दायरे से विरासत में मिला है, अभी तक उपलब्ध नहीं है।

करना:

  • नियंत्रक तर्क को परिभाषित करें
  • गुंजाइश चर आरंभ करें

ऐसा न करें:

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

खुशी है कि आपने निर्देशक के भीतर नियंत्रक का उल्लेख किया है जो गुंजाइश को शुरू करने के लिए एक शानदार जगह है। मुझे यह पता लगाने में कठिन समय था।
jsbisht 15

1
नियंत्रक "गुंजाइश शुरू नहीं करता है", यह केवल उस दायरे तक पहुंचता है जो पहले से ही इसके स्वतंत्र रूप से शुरू किया गया है।
दिमित्री जैतसेव

@DmitriZaitsev विवरण के लिए अच्छा ध्यान। मैंने पाठ में संशोधन किया है।
इज़्हाकी

19

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

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

यह आमतौर पर प्रदान किए गए DOM को और अधिक हेरफेर करने के लिए एक जगह है।

करना:

  • DOM (रेंडर किया गया, और इस तरह त्वरित) तत्वों को हेरफेर करें।
  • ईवेंट हैंडलर संलग्न करें।
  • बाल तत्वों का निरीक्षण करें।
  • विशेषताओं पर अवलोकन सेट करें।
  • गुंजाइश पर घड़ियों सेट करें।

9
यदि कोई लिंक लिंक फ़ंक्शन (प्री-लिंक या पोस्ट-लिंक के बिना) का उपयोग कर रहा है, तो यह जानना अच्छा है कि यह पोस्ट-लिंक के बराबर है।
आसफ डेविड

15

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

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

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

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

ऐसा न करें:

  • बाल तत्वों का निरीक्षण करें (वे अभी तक प्रदान नहीं किए जा सकते हैं, गुंजाइश के लिए बाध्य हैं, आदि)।
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.