angularjs - कोणीय निर्देश-संकलन, नियंत्रक, प्री-लिंक और पोस्ट-लिंक का उपयोग कब और कैसे करें
angularjs-directive (6)
एक कोणीय निर्देश लिखते समय, कोई भी निम्नलिखित कार्यों में से किसी एक का उपयोग कर सकता है ताकि डोम व्यवहार, सामग्री और उस तत्व को देख सकें जिस पर निर्देश घोषित किया गया है:
- संकलन
- नियंत्रक
- पूर्व लिंक
- बाद लिंक
ऐसा कुछ भ्रम प्रतीत होता है क्योंकि किस फ़ंक्शन को उपयोग करना चाहिए। इस सवाल में शामिल हैं:
निर्देश मूल बातें
- विभिन्न कार्यों की घोषणा कैसे करें?
- स्रोत टेम्पलेट और एक उदाहरण टेम्पलेट के बीच क्या अंतर है?
- किस क्रम में निर्देश कार्यों को निष्पादित किया जाता है?
- इन फ़ंक्शन कॉल के बीच और क्या होता है?
फंक्शन प्रकृति, क्या करें और न करें
- Compile
- Controller
- Pre-link
- Post-link
संबंधित सवाल:
- निर्देश: लिंक बनाम संकलन बनाम नियंत्रक ।
- Angular.js निर्देश को परिभाषित करते समय 'नियंत्रक', 'लिंक' और 'संकलन' कार्यों के बीच अंतर ।
- कोणीय में संकलन और लिंक फ़ंक्शन के बीच क्या अंतर है ।
- AngularJS निर्देशों में पूर्व-संकलन और पोस्ट-संकलन तत्व के बीच अंतर? ।
- कोणीय जेएस निर्देश - टेम्पलेट, संकलन या लिंक? ।
- कोणीय जेएस निर्देशों में पोस्ट लिंक बनाम पूर्व लिंक पोस्ट करें ।
इन फ़ंक्शन कॉल के बीच और क्या होता है?
विभिन्न निर्देश कार्यों को दो अन्य कोणीय कार्यों के भीतर से निष्पादित किया जाता है जिन्हें $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>
किस क्रम में निर्देश कार्यों को निष्पादित किया जाता है?
एक ही निर्देश के लिए
निम्नलिखित 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 बार)। ये क्लोन उदाहरण टेम्पलेट हैं, प्रत्येक डीओएम में दिखाई देगा और प्रासंगिक दायरे से बंधेगा।