त्वरित उत्तर :
एक बच्चे का दायरा सामान्य रूप से मूल रूप से अपने मूल दायरे से विरासत में मिलता है, लेकिन हमेशा नहीं। इस नियम का एक अपवाद इसके साथ एक निर्देश है scope: { ... }
- यह एक "अलग" गुंजाइश बनाता है जो प्रोटोटाइपिक रूप से विरासत में नहीं आता है। यह निर्माण अक्सर "पुन: प्रयोज्य घटक" निर्देशन बनाते समय उपयोग किया जाता है।
बारीकियों के लिए, गुंजाइश वंशानुक्रम सामान्य रूप से सीधा होता है ... जब तक आपको बच्चे के दायरे में 2-वे डेटा बाइंडिंग (यानी, तत्व, एनजी-मॉडल) की आवश्यकता नहीं होती है। यदि आप चाइल्ड स्कोप के अंदर से पैरेंट स्कोप में एक आदिम (जैसे, संख्या, स्ट्रिंग, बूलियन) को बांधने की कोशिश करते हैं तो एनजी-रिपीट, एनजी-स्विच और एनजी-शामिल आपको यात्रा कर सकते हैं । यह उस तरह से काम नहीं करता है जिस तरह से अधिकांश लोगों को उम्मीद है कि यह काम करना चाहिए। चाइल्ड स्कोप को अपनी संपत्ति मिलती है जो उसी नाम की मूल संपत्ति को छुपाती है / छाया देती है। आपके वर्कअराउंड हैं
- अपने मॉडल के लिए माता-पिता में वस्तुओं को परिभाषित करें, फिर बच्चे में उस वस्तु की एक संपत्ति का संदर्भ दें: parentObj.someProp
- $ parent.parentScopeProperty का उपयोग करें (हमेशा संभव नहीं, लेकिन जहां संभव हो वहां 1 से आसान)
- पैरेंट स्कोप पर एक फंक्शन को परिभाषित करें, और इसे बच्चे से कॉल करें (हमेशा संभव नहीं)
नई AngularJS डेवलपर्स अक्सर कि एहसास नहीं है ng-repeat
, ng-switch
, ng-view
, ng-include
और ng-if
सभी नए बच्चे स्कोप बनाते हैं, तो समस्या अक्सर दिखाई देता है जब इन निर्देशों शामिल हैं। ( समस्या के त्वरित चित्रण के लिए इस उदाहरण को देखें ।)
आदिम के साथ इस मुद्दे को हमेशा 'एक' के "सर्वोत्तम अभ्यास" का पालन करके आसानी से टाला जा सकता है । अपने एनजी-मॉडल में - 3 मिनट के मूल्य देखें। Misko के साथ आदिम बाध्यकारी मुद्दे को दर्शाता है ng-switch
।
होने '।' आपके मॉडल में यह सुनिश्चित होगा कि प्रोटोटाइप विरासत में मिला है। तो, उपयोग करें
<input type="text" ng-model="someObj.prop1">
<!--rather than
<input type="text" ng-model="prop1">`
-->
लंबे उत्तर :
जावास्क्रिप्ट प्रोटोटाइप इनहेरिटेंस
AngularJS wiki पर भी रखा गया: https://github.com/angular/angular.js/wiki/Understanding-Scopes
पहले प्रोटोटाइप प्रोटोटाइप की ठोस समझ होना जरूरी है, खासकर यदि आप सर्वर-साइड बैकग्राउंड से आ रहे हैं और आप क्लास-आइकल इनहेरिटेंस से अधिक परिचित हैं। तो चलिए पहले समीक्षा करते हैं।
मान लीजिए कि पेरेंटस्कोप में एस्ट्रिंज, अम्बर, ऐरे, ऑबजेक्ट और एफंक्शन जैसे गुण हैं। अगर चाइल्डस्कोप प्रोटोटाइप से विरासत में मिला है, तो हमारे पास है:
(ध्यान दें कि अंतरिक्ष को बचाने के लिए, मैं anArray
वस्तु को तीन अलग-अलग ग्रे शाब्दिकों के साथ एक नीली वस्तु के बजाय अपने तीन मूल्यों के साथ एक नीली वस्तु के रूप में दिखाता हूं ।)
यदि हम चाइल्ड स्कोप से पेरेंटस्कोप पर परिभाषित प्रॉपर्टी को एक्सेस करने की कोशिश करते हैं, तो जावास्क्रिप्ट पहले चाइल्ड स्कोप को देखेगा, प्रॉपर्टी को नहीं खोजेगा, उसके बाद इनहेरिटेड स्कोप को देखेगा, और प्रॉपर्टी को ढूंढेगा। (यदि यह पैरेंटस्कोप में प्रॉपर्टी नहीं मिली, तो यह प्रोटोटाइप चेन जारी रहेगा ... रूट स्कोप तक सभी तरह से)। तो, ये सभी सत्य हैं:
childScope.aString === 'parent string'
childScope.anArray[1] === 20
childScope.anObject.property1 === 'parent prop1'
childScope.aFunction() === 'parent output'
मान लीजिए कि हम ऐसा करते हैं:
childScope.aString = 'child string'
प्रोटोटाइप चेन से परामर्श नहीं किया जाता है, और चाइल्डस्कोप में एक नई स्ट्रॉन्ग प्रॉपर्टी जोड़ी जाती है। यह नई प्रॉपर्टी उसी नाम से पेरेंटस्कोप प्रॉपर्टी को छुपाती / छाया देती है। यह बहुत महत्वपूर्ण हो जाएगा जब हम एनजी-रिपीट और एनजी-निचे चर्चा करेंगे।
मान लीजिए कि हम ऐसा करते हैं:
childScope.anArray[1] = '22'
childScope.anObject.property1 = 'child prop1'
प्रोटोटाइप चेन से सलाह ली जाती है क्योंकि ऑब्जेक्ट (एयरर और ऑबजेक्ट) चाइल्डस्कोप में नहीं पाए जाते हैं। ऑब्जेक्ट्स पेरेंटस्कोप में पाए जाते हैं, और मूल ऑब्जेक्ट्स पर गुण मान अपडेट किए जाते हैं। चाइल्डस्कोप में कोई नया गुण नहीं जोड़ा गया है; कोई नई वस्तु नहीं बनाई गई है। (ध्यान दें कि जावास्क्रिप्ट सरणियों और फ़ंक्शन भी ऑब्जेक्ट हैं।)
मान लीजिए कि हम ऐसा करते हैं:
childScope.anArray = [100, 555]
childScope.anObject = { name: 'Mark', country: 'USA' }
प्रोटोटाइप चेन से परामर्श नहीं किया जाता है, और चाइल्ड स्कोप को दो नए ऑब्जेक्ट प्रॉपर्टी मिलती हैं जो समान नामों के साथ पेरेंटस्कोप ऑब्जेक्ट प्रॉपर्टी को छिपाते / छाया देते हैं।
टेकअवे:
- यदि हम चाइल्डस्कोप.प्रोपर्टीएक्स पढ़ते हैं, और चाइल्डस्कोप में प्रॉपर्टीएक्स है, तो प्रोटोटाइप चेन से परामर्श नहीं किया जाता है।
- यदि हम childScope.propertyX सेट करते हैं, तो प्रोटोटाइप श्रृंखला से परामर्श नहीं किया जाता है।
एक अंतिम परिदृश्य:
delete childScope.anArray
childScope.anArray[1] === 22 // true
हमने पहले चाइल्डस्कोप प्रॉपर्टी को डिलीट किया, फिर जब हम प्रॉपर्टी को फिर से एक्सेस करने की कोशिश करते हैं, तो प्रोटोटाइप चेन से सलाह ली जाती है।
कोणीय घेरा वंशानुक्रम
दावेदार:
- निम्नलिखित नए स्कोप बनाते हैं, और प्रोटोटाइपिक रूप से इनहेरिट करते हैं: एनजी-रिपीट, एनजी-शामिल, एनजी-स्विच, एनजी-नियंत्रक, निर्देश के साथ
scope: true
, निर्देश transclude: true
।
- निम्नलिखित एक नया दायरा बनाता है जो प्रोटोटाइपिक रूप से विरासत में नहीं मिलता है: साथ निर्देश
scope: { ... }
। यह इसके बजाय एक "अलग" गुंजाइश बनाता है।
ध्यान दें, डिफ़ॉल्ट रूप से, निर्देश नए दायरे नहीं बनाते हैं - यानी, डिफ़ॉल्ट है scope: false
।
एनजी-शामिल
मान लें कि हमारे नियंत्रक में है:
$scope.myPrimitive = 50;
$scope.myObject = {aNumber: 11};
और हमारे HTML में:
<script type="text/ng-template" id="/tpl1.html">
<input ng-model="myPrimitive">
</script>
<div ng-include src="'/tpl1.html'"></div>
<script type="text/ng-template" id="/tpl2.html">
<input ng-model="myObject.aNumber">
</script>
<div ng-include src="'/tpl2.html'"></div>
प्रत्येक एनजी-शामिल में एक नया चाइल्ड स्कोप उत्पन्न होता है, जो मूल रूप से पेरेंट स्कोप से विरासत में प्राप्त होता है।
पहले इनपुट टेक्स्टबॉक्स में टाइपिंग ("77") के कारण बच्चे के दायरे में एक नया myPrimitive
स्कोप प्रॉपर्टी मिलती है जो उसी नाम की पेरेंट स्कोप प्रॉपर्टी को छुपाता / छाया देता है। यह शायद वह नहीं है जो आप चाहते हैं / उम्मीद करते हैं।
दूसरे इनपुट टेक्स्टबॉक्स में टाइप करने (कहना, "99") का परिणाम नई बाल संपत्ति नहीं है। क्योंकि tpl2.html मॉडल को ऑब्जेक्ट प्रॉपर्टी से बांधता है, जब एनपोडल ऑब्जेक्ट ऑब्जेक्ट myObject के लिए दिखता है, तो प्रोटोटाइप इनहेरिटेंस किक करता है - यह इसे पेरेंट स्कोप में पाता है।
हम $ माता-पिता का उपयोग करने के लिए पहले टेम्पलेट को फिर से लिख सकते हैं, अगर हम अपने मॉडल को आदिम से वस्तु में बदलना नहीं चाहते हैं:
<input ng-model="$parent.myPrimitive">
इस इनपुट टेक्स्टबॉक्स में टाइपिंग ("22") का परिणाम नई बाल संपत्ति नहीं है। मॉडल अब माता-पिता के दायरे की संपत्ति के लिए बाध्य है (क्योंकि $ माता-पिता एक बच्चे की गुंजाइश संपत्ति है जो माता-पिता के दायरे को संदर्भित करता है)।
सभी स्कोप (प्रोटोटाइप या नहीं) के लिए, कोणीय हमेशा पैरेन्ट-चाइल्ड रिलेशनशिप (यानी, एक पदानुक्रम) को ट्रैक करता है, स्कोप गुण $ पैरेंट, $$ चाइल्डहेड और $ $ चाइल्डटेल के माध्यम से। मैं आम तौर पर आरेख में इन गुंजाइश गुण नहीं दिखाते हैं।
उन परिदृश्यों के लिए जहां फ़ॉर्म तत्व शामिल नहीं हैं, एक अन्य समाधान है कि आदिम को संशोधित करने के लिए मूल कार्यक्षेत्र पर एक फ़ंक्शन को परिभाषित किया जाए। फिर सुनिश्चित करें कि बच्चा हमेशा इस फ़ंक्शन को कॉल करता है, जो कि प्रोटोटाइप विरासत के कारण बच्चे के दायरे में उपलब्ध होगा। उदाहरण के लिए,
// in the parent scope
$scope.setMyPrimitive = function(value) {
$scope.myPrimitive = value;
}
यहां एक नमूना नमूना है जो इस "मूल फ़ंक्शन" दृष्टिकोण का उपयोग करता है। (फिडल को इस उत्तर के भाग के रूप में लिखा गया था: https://stackoverflow.com/a/14104318/215945 ।)
Https://stackoverflow.com/a/13782671/215945 और भी देखें https://github.com/angular/angular.js/issues/1267 ।
एनजी स्विच
एनजी-स्विच गुंजाइश विरासत एनजी-शामिल की तरह काम करता है। इसलिए यदि आपको पेरेंट स्कोप में प्रिमिटिव के लिए 2-वे डेटा बाइंडिंग की आवश्यकता है, तो $ पेरेंट का उपयोग करें, या मॉडल को ऑब्जेक्ट के रूप में बदलें और फिर उस ऑब्जेक्ट की प्रॉपर्टी से बाइंड करें। इससे चाइल्ड स्कोप छिपने / पैरेंट स्कोप प्रॉपर्टीज की शैडोइंग से बच जाएगा।
यह सभी देखें AngularJS , स्विच-केस की गुंजाइश है?
एनजी-दोहराने
एनजी-रिपीट थोड़ा अलग तरीके से काम करता है। मान लें कि हमारे नियंत्रक में है:
$scope.myArrayOfPrimitives = [ 11, 22 ];
$scope.myArrayOfObjects = [{num: 101}, {num: 202}]
और हमारे HTML में:
<ul><li ng-repeat="num in myArrayOfPrimitives">
<input ng-model="num">
</li>
<ul>
<ul><li ng-repeat="obj in myArrayOfObjects">
<input ng-model="obj.num">
</li>
<ul>
प्रत्येक आइटम / पुनरावृत्ति के लिए, एनजी-रिपीट एक नया स्कोप बनाता है, जो मूल रूप से पेरेंट स्कोप से विरासत में मिलता है, लेकिन यह नए चाइल्ड स्कोप पर एक नए प्रॉपर्टी के लिए आइटम का मान भी प्रदान करता है । (नई प्रॉपर्टी का नाम लूप वेरिएबल का नाम है।) यहाँ एनजी-रिपीट के लिए कोणीय स्रोत कोड वास्तव में क्या है:
childScope = scope.$new(); // child scope prototypically inherits from parent scope
...
childScope[valueIdent] = value; // creates a new childScope property
यदि आइटम एक आदिम (myArrayOfPrimatics के रूप में) है, तो अनिवार्य रूप से मूल्य की एक प्रति नए बच्चे की गुंजाइश संपत्ति को सौंपी जाती है। चाइल्ड स्कोप प्रॉपर्टी की वैल्यू बदलना (यानी, एनजी-मॉडल का उपयोग करना, इसलिए चाइल्ड स्कोप num
) ऐरे को पेरेंट स्कोप रेफरेंस नहीं बदलता है। इसलिए ऊपर दिए गए पहले एनजी-रिपीट में, प्रत्येक चाइल्ड स्कोप को एक ऐसी num
प्रॉपर्टी मिलती है, जो myArrayOfPrimatives ऐरे से स्वतंत्र होती है:
यह एनजी-रिपीट काम नहीं करेगा (जैसे आप चाहते हैं / यह अपेक्षा करें)। टेक्स्टबॉक्स में टाइप करने से ग्रे बॉक्स में मान बदल जाते हैं, जो केवल चाइल्ड स्कोप में दिखाई देते हैं। हम जो चाहते हैं वह इनपुट के लिए है myArrayOfPrimatics सरणी को प्रभावित करने के लिए, न कि एक बाल गुंजाइश आदिम संपत्ति। इसे पूरा करने के लिए, हमें वस्तुओं की एक सरणी होने के लिए मॉडल को बदलने की आवश्यकता है।
इसलिए, यदि वस्तु एक वस्तु है, तो मूल वस्तु (प्रति नहीं) का एक संदर्भ नए बच्चे की गुंजाइश संपत्ति को सौंपा जाता है। बच्चे गुंजाइश संपत्ति के मूल्य में परिवर्तन करना (अर्थात एनजी-मॉडल का उपयोग, इसलिए obj.num
) करता वस्तु माता पिता गुंजाइश संदर्भ बदल जाते हैं। तो ऊपर दूसरे एनजी-रिपीट में, हमारे पास है:
(मैं एक लाइन ग्रे रंग से बस इतना करता हूं कि यह स्पष्ट है कि यह कहां जा रहा है।)
यह उम्मीद के मुताबिक काम करता है। टेक्स्टबॉक्स में टाइप करने से ग्रे बॉक्स में मान बदल जाते हैं, जो बच्चे और माता-पिता दोनों को दिखाई देते हैं।
यह भी देखें एनजी-मॉडल के साथ कठिनाई, एनजी-दोहराने, और आदानों और
https://stackoverflow.com/a/13782671/215945 के
एनजी नियंत्रक
एनजी-नियंत्रक परिणामों का उपयोग करते हुए नेस्टिंग नियंत्रक सामान्य प्रोटोटाइप विरासत में, एनजी-शामिल और एनजी-स्विच की तरह, इसलिए एक ही तकनीक लागू होती है। हालांकि, "इसे दो नियंत्रकों के लिए $ स्कोप इनहेरिटेंस के माध्यम से जानकारी साझा करने के लिए बुरा रूप माना जाता है" - http://onehungrymind.com/angularjs-sticky-notes-pt-1-altecture/
बीच डेटा साझा करने के लिए एक सेवा का उपयोग किया जाना चाहिए इसके बजाय नियंत्रकों।
(यदि आप वास्तव में कंट्रोलर्स स्कोप इनहेरिटेंस के माध्यम से डेटा साझा करना चाहते हैं, तो आपको कुछ भी करने की आवश्यकता नहीं है। चाइल्ड स्कोप के पास सभी पेरेंट स्कोप प्रॉपर्टीज की एक्सेस होगी। लोड करते या नेविगेट करते समय कंट्रोलर लोड ऑर्डर भी अलग-अलग होते हैं। )
निर्देशों
- चूक (
scope: false
) - निर्देश एक नया क्षेत्र नहीं बनाता है, इसलिए यहां कोई विरासत नहीं है। यह आसान है, लेकिन खतरनाक भी है, क्योंकि, एक निर्देश शायद यह सोच सकता है कि यह एक नई संपत्ति बना रहा है, जब वास्तव में यह एक मौजूदा संपत्ति को रोक रहा है। निर्देश लिखने के लिए यह एक अच्छा विकल्प नहीं है जो पुन: प्रयोज्य घटकों के रूप में अभिप्रेत है।
scope: true
- निर्देश एक नया चाइल्ड स्कोप बनाता है जो मूल रूप से पेरेंट स्कोप से विरासत में मिला है। यदि एक से अधिक निर्देश (एक ही DOM तत्व पर) एक नए दायरे का अनुरोध करते हैं, तो केवल एक नया चाइल्ड स्कोप बनाया जाता है। चूंकि हमारे पास "सामान्य" प्रोटोटाइप विरासत है, यह एनजी-शामिल और एनजी-स्विच की तरह है, इसलिए पेरेंट स्कोप प्रिमिटिव्स के लिए बाइंडिंग 2-वे डेटा से सावधान रहें, और पेरेंट स्कोप प्रॉपर्टीज के चाइल्ड स्कोप हाइडिंग / शैडोइंग।
scope: { ... }
- निर्देश एक नया पृथक / पृथक क्षेत्र बनाता है। यह प्रोटोटाइपिक रूप से विरासत में नहीं मिलता है। पुन: प्रयोज्य घटकों को बनाते समय यह आमतौर पर आपका सबसे अच्छा विकल्प होता है, क्योंकि निर्देश गलती से मूल अंश को नहीं पढ़ या संशोधित कर सकता है। हालांकि, इस तरह के निर्देशों को अक्सर कुछ मूल गुंजाइश गुणों तक पहुंच की आवश्यकता होती है। ऑब्जेक्ट हैश का उपयोग पेरेंट स्कोप और आइसोलेट स्कोप के बीच दो-तरफ़ा बाइंडिंग ('=' का उपयोग करके) या वन-वे बाइंडिंग ('@') का उपयोग करने के लिए किया जाता है। पैरेंट स्कोप एक्सप्रेशन के लिए बाध्य करने के लिए 'और' भी है। तो, ये सभी स्थानीय स्कोप गुण बनाते हैं जो मूल स्कोप से प्राप्त होते हैं। ध्यान दें कि बाइंडिंग सेट करने में मदद करने के लिए विशेषताओं का उपयोग किया जाता है - आप ऑब्जेक्ट हैश में केवल पैरेंट स्कोप प्रॉपर्टी के नाम का संदर्भ नहीं दे सकते, आपको एक विशेषता का उपयोग करना होगा। उदाहरण के लिए, यह काम नहीं करेगा यदि आप मूल संपत्ति में बाँधना चाहते हैंparentProp
अलग दायरे में: <div my-directive>
और scope: { localProp: '@parentProp' }
। प्रत्येक माता-पिता की संपत्ति को निर्दिष्ट करने के लिए एक विशेषता का उपयोग किया जाना चाहिए जो निर्देश को बांधना चाहता है: <div my-directive the-Parent-Prop=parentProp>
और scope: { localProp: '@theParentProp' }
।
गुंजाइश के __proto__
संदर्भ वस्तु को अलग करें । आइसोलेट स्कोप के $ पेरेंट पेरेंट स्कोप को संदर्भित करते हैं, इसलिए यद्यपि यह अलग-थलग है और पेरेंट स्कोप से प्रोटोटाइप से इनहेरिट नहीं होता है, फिर भी यह एक चाइल्ड स्कोप है।
नीचे दी गई तस्वीर के लिए हमारे पास
<my-directive interpolated="{{parentProp1}}" twowayBinding="parentProp2">
और
scope: { interpolatedProp: '@interpolated', twowayBindingProp: '=twowayBinding' }
इसके अलावा, मान लीजिए कि यह निर्देशन अपने लिंकिंग फंक्शन में करता है: scope.someIsolateProp = "I'm isolated"
अलग-अलग स्कोप की अधिक जानकारी के लिए देखें http://onehungrymind.com/angularjs-sticky-notes-pt-2-isolated-scope/
transclude: true
- निर्देश एक नया "ट्रांसकोडेड" चाइल्ड स्कोप बनाता है, जो मूल रूप से पेरेंट स्कोप से विरासत में मिला है। ट्रांसकोडेड और अलग-थलग स्कोप (यदि कोई हो) भाई-बहन हैं - प्रत्येक स्कोप की $ पेरेंट प्रॉपर्टी एक ही पेरेंट स्कोप का संदर्भ देती है। जब एक transcluded और एक अलग गुंजाइश दोनों मौजूद होते हैं, तो अलग-अलग गुंजाइश संपत्ति $ $ अगली अगली ट्रांसकोड किए गए दायरे को संदर्भित करेगी। मैं transcluded गुंजाइश के साथ किसी भी बारीकियों के बारे में पता नहीं कर रहा हूँ।
नीचे दी गई तस्वीर के लिए, इस जोड़ के साथ ऊपर दिए गए निर्देश को मानें:transclude: true
इस फिडेल में एक showScope()
फ़ंक्शन होता है जिसका उपयोग एक अलग और ट्रांसकोड किए गए दायरे की जांच करने के लिए किया जा सकता है। टिप्पणियों में निर्देश देखें।
सारांश
स्कोप चार प्रकार के होते हैं:
- सामान्य प्रोटोटाइप गुंजाइश विरासत - एनजी-शामिल, एनजी-स्विच, एनजी-नियंत्रक, निर्देश के साथ
scope: true
- एक कॉपी / असाइनमेंट के साथ सामान्य प्रोटोटाइप गुंजाइश विरासत - एनजी-रिपीट। एनजी-रिपीट का प्रत्येक पुनरावृत्ति एक नया चाइल्ड स्कोप बनाता है, और उस नए चाइल्ड स्कोप को हमेशा एक नई प्रॉपर्टी मिलती है।
- अलग गुंजाइश - साथ निर्देश
scope: {...}
। यह एक प्रोटोटाइप नहीं है, लेकिन '=', '@', और '&' माता-पिता के गुण गुणों तक पहुँचने के लिए एक तंत्र प्रदान करता है।
- transcluded गुंजाइश - साथ निर्देश
transclude: true
। यह एक सामान्य प्रोटोटाइप गुंजाइश वंशानुक्रम भी है, लेकिन यह किसी भी अलग-अलग दायरे का सहोदर भी है।
सभी स्कोप (प्रोटोटाइप या नहीं) के लिए, कोणीय हमेशा माता-पिता-बच्चे के रिश्ते (यानी, एक पदानुक्रम) को ट्रैक करता है, गुणों के माध्यम से $ पैर और $ $ चाइल्डहेड और $ $ चाइल्डटेल।
आरेखों के साथ उत्पन्न हुए थे Graphviz* ".dot" फाइलें, जो गिटहब पर हैं । टिम कैसवेल का " लर्निंग जावास्क्रिप्ट विद ऑब्जेक्ट ग्राफ्स " रेखाचित्रों के लिए ग्राफविज़ का उपयोग करने की प्रेरणा थी।