AngularJS नियंत्रकों में 'यह' बनाम $ गुंजाइश




angularjs-scope this (6)

AngularJS के मुखपृष्ठ के "घटक बनाएं" अनुभाग में , यह उदाहरण है:

controller: function($scope, $element) {
  var panes = $scope.panes = [];
  $scope.select = function(pane) {
    angular.forEach(panes, function(pane) {
      pane.selected = false;
    });
    pane.selected = true;
  }
  this.addPane = function(pane) {
    if (panes.length == 0) $scope.select(pane);
    panes.push(pane);
  }
}

ध्यान दें कि select विधि $scope कैसे जोड़ा जाता $scope , लेकिन इसमें addPane विधि जोड़ दी जाती है। अगर मैं इसे $scope.addPane , तो कोड टूट जाता है।

दस्तावेज कहता है कि वास्तव में एक अंतर है, लेकिन यह उल्लेख नहीं करता कि अंतर क्या है:

कोणीय (पूर्व 1.0 आरसी) के पिछले संस्करणों ने आपको $scope विधि के साथ this विनिमय के लिए उपयोग करने की अनुमति दी, लेकिन यह अब मामला नहीं है। this दायरे पर परिभाषित विधियों के अंदर और $scope अदला-बदली करने योग्य हैं (कोणीय this $scope सेट करता है), लेकिन अन्यथा आपके नियंत्रक कन्स्ट्रक्टर के अंदर नहीं।

AngularJS नियंत्रकों में this और $scope कैसे काम करता है?


"AngularJS नियंत्रकों में this और $scope कैसे काम करती है?"

संक्षिप्त उत्तर :

  • this
    • जब नियंत्रक कन्स्ट्रक्टर फ़ंक्शन कहा जाता है, तो this नियंत्रक होता है।
    • जब $scope ऑब्जेक्ट पर परिभाषित फ़ंक्शन को कॉल किया जाता है, तो this तब होता है जब फ़ंक्शन को कॉल किया गया था "। यह $scope (हो सकता है!) $scope हो सकता है जिस पर फ़ंक्शन परिभाषित किया गया है। तो, फ़ंक्शन के अंदर, this और $scope समान नहीं हो सकता है।
  • $scope
    • प्रत्येक नियंत्रक के पास $scope ऑब्जेक्ट होता है।
    • एक नियंत्रक (कन्स्ट्रक्टर) फ़ंक्शन मॉडल गुणों और कार्यों / व्यवहार को उसके संबंधित $scope पर सेट करने के लिए ज़िम्मेदार $scope
    • इस $scope ऑब्जेक्ट (और पैरेंट स्कोप ऑब्जेक्ट्स, यदि प्रोटोटाइपिकल विरासत खेल में है) पर परिभाषित केवल विधियां HTML / व्यू से पहुंच योग्य हैं। उदाहरण के लिए, ng-click , फिल्टर इत्यादि से।

लंबा जवाब :

एक नियंत्रक समारोह एक जावास्क्रिप्ट कन्स्ट्रक्टर समारोह है। जब कन्स्ट्रक्टर फ़ंक्शन निष्पादित करता है (उदाहरण के लिए, जब कोई दृश्य लोड होता है), this (यानी, "फ़ंक्शन संदर्भ") नियंत्रक ऑब्जेक्ट पर सेट होता है। इसलिए "टैब" नियंत्रक कन्स्ट्रक्टर फ़ंक्शन में, जब ऐडपैन फ़ंक्शन बनाया जाता है

this.addPane = function(pane) { ... }

यह $ स्कोप पर नहीं, नियंत्रक ऑब्जेक्ट पर बनाया गया है। दृश्य addPane फ़ंक्शन नहीं देख सकते हैं - उनके पास केवल $ स्कोप पर परिभाषित कार्यों तक पहुंच है। दूसरे शब्दों में, एचटीएमएल में, यह काम नहीं करेगा:

<a ng-click="addPane(newPane)">won't work</a>

"टैब" नियंत्रक कन्स्ट्रक्टर फ़ंक्शन निष्पादित करने के बाद, हमारे पास निम्नलिखित हैं:

धराशायी काली रेखा प्रोटोटाइप विरासत को इंगित करती है - एक अलग गुंजाइश प्रोटोटाइप Scope से विरासत में प्राप्त होती है। (यह प्रोटोटाइप रूप से उस दायरे से प्राप्त नहीं होता है जहां एचटीएमएल में निर्देश का सामना किया गया था।)

अब, फलक निर्देशक का लिंक फ़ंक्शन टैब निर्देश के साथ संवाद करना चाहता है (जिसका वास्तव में इसका अर्थ यह है कि इसे किसी भी तरह से $ स्कोप को अलग करने वाले टैब को प्रभावित करने की आवश्यकता है)। घटनाओं का उपयोग किया जा सकता है, लेकिन एक और तंत्र है कि फलक निर्देश के लिए टैब नियंत्रक की require है। (टैब के दायरे की require के लिए फलक निर्देश के लिए कोई तंत्र नहीं प्रतीत होता है।)

तो, यह सवाल पूछता है: अगर हमारे पास केवल टैब नियंत्रक तक पहुंच है, तो हम $ स्कोप को अलग करने वाले टैब तक पहुंच कैसे प्राप्त कर सकते हैं (जो हम वास्तव में चाहते हैं)?

खैर, लाल बिंदीदार रेखा जवाब है। ऐडपेन () फ़ंक्शन का "स्कोप" (मैं जावास्क्रिप्ट के फ़ंक्शन स्कोप / क्लोजर का जिक्र कर रहा हूं) फ़ंक्शन को $ स्कोप को अलग करने वाले टैब तक पहुंच प्रदान करता है। Ie, addPane () को उपरोक्त आरेख में "टैब IsolateScope" तक पहुंच है क्योंकि addPane () को परिभाषित किया गया था। (यदि हमने $ स्कोप ऑब्जेक्ट टैब पर ऐडपेन () को परिभाषित किया है, तो फलक निर्देश के पास इस फ़ंक्शन तक पहुंच नहीं होगी, और इसलिए टैब के दायरे के साथ संवाद करने का कोई तरीका नहीं होगा।)

अपने प्रश्न के दूसरे भाग का जवाब देने के लिए: how does $scope work in controllers? :

$ स्कोप पर परिभाषित कार्यों के भीतर, this "प्रभाव में $ स्कोप" पर सेट किया गया है जहां फ़ंक्शन को कॉल किया गया था "। मान लें कि हमारे पास निम्नलिखित HTML है:

<div ng-controller="ParentCtrl">
   <a ng-click="logThisAndScope()">log "this" and $scope</a> - parent scope
   <div ng-controller="ChildCtrl">
      <a ng-click="logThisAndScope()">log "this" and $scope</a> - child scope
   </div>
</div>

और ParentCtrl (पूरी तरह से) है

$scope.logThisAndScope = function() {
    console.log(this, $scope)
}

पहले लिंक पर क्लिक करने से यह पता चलता है कि this और $scope समान हैं, क्योंकि " फ़ंक्शन कहलाते समय प्रभाव में दायरा " ParentCtrl जुड़ा हुआ दायरा है।

दूसरे लिंक पर क्लिक करने से this पता चलता है और $scope समान नहीं है, क्योंकि " फ़ंक्शन कहलाते समय प्रभावी रूप से दायरा" ChildCtrl जुड़ा हुआ दायरा है। तो यहां, this ChildCtrl के $scope सेट है। विधि के अंदर, $scope अभी भी ParentCtrl का $ स्कोप है।

Fiddle

मैं इसे $ स्कोप पर परिभाषित फ़ंक्शन के अंदर उपयोग करने का प्रयास नहीं करता, क्योंकि यह भ्रमित हो जाता है कि कौन सा $ गुंजाइश प्रभावित हो रहा है, विशेष रूप से उस एनजी-दोहराने, एनजी-शामिल, एनजी-स्विच, और निर्देशों पर विचार करने से सभी अपने बच्चे के स्कॉप्स बना सकते हैं ।


इस कोर्स में ( https://www.codeschool.com/courses/shaping-up-with-angular-js ) वे बताते हैं कि "यह" और कई अन्य सामानों का उपयोग कैसे करें।

यदि आप "इस" विधि के माध्यम से नियंत्रक को विधि जोड़ते हैं, तो आपको इसे नियंत्रक के नाम "डॉट" के साथ अपनी संपत्ति या विधि के साथ दृश्य में कॉल करना होगा।

उदाहरण के लिए दृश्य में अपने नियंत्रक का उपयोग करके आपके पास कोड हो सकता है:

    <div data-ng-controller="YourController as aliasOfYourController">

       Your first pane is {{aliasOfYourController.panes[0]}}

    </div>

$ स्कोप में एक अलग 'यह' है तो नियंत्रक 'यह'। इस प्रकार यदि आप नियंत्रक के अंदर एक console.log (यह) डालते हैं तो यह आपको एक ऑब्जेक्ट (नियंत्रक) देता है और यह .addPane () नियंत्रक ऑब्जेक्ट में addPane विधि जोड़ता है। लेकिन $ स्कोप के पास अलग-अलग दायरे हैं और इसके दायरे में सभी विधियों को $ scope.methodName () द्वारा accesed की आवश्यकता है। नियंत्रक के अंदर this.methodName() नियंत्रक ऑब्जेक्ट के अंदर this.methodName() जोड़ने का मतलब है। $scope.functionName() HTML और अंदर है

$scope.functionName(){
    this.name="Name";
    //or
    $scope.myname="myname"//are same}

इस कोड को अपने संपादक में पेस्ट करें और देखने के लिए कंसोल खोलें ...

 <!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>this $sope vs controller</title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.7/angular.min.js"></script>
    <script>
        var app=angular.module("myApp",[]);
app.controller("ctrlExample",function($scope){
          console.log("ctrl 'this'",this);
          //this(object) of controller different then $scope
          $scope.firstName="Andy";
          $scope.lastName="Bot";
          this.nickName="ABot";
          this.controllerMethod=function(){

            console.log("controllerMethod ",this);
          }
          $scope.show=function(){
              console.log("$scope 'this",this);
              //this of $scope
              $scope.message="Welcome User";
          }

        });
</script>
</head>
<body ng-app="myApp" >
<div ng-controller="ctrlExample">
       Comming From $SCOPE :{{firstName}}
       <br><br>
       Comming from $SCOPE:{{lastName}}
       <br><br>
       Should Come From Controller:{{nickName}}
       <p>
            Blank nickName is because nickName is attached to 
           'this' of controller.
       </p>

       <br><br>
       <button ng-click="controllerMethod()">Controller Method</button>

       <br><br>
       <button ng-click="show()">Show</button>
       <p>{{message}}</p>

   </div>

</body>
</html>

इसका कारण 'एडपेन' को सौंपा गया है क्योंकि <pane> निर्देश है।

pane निर्देश के लिए require: '^tabs' , जो टैब नियंत्रक ऑब्जेक्ट को पैरेंट फ़ंक्शन में पैरेंट निर्देश से रखता है।

addPane को असाइन किया गया है ताकि pane लिंक फ़ंक्शन इसे देख सके। फिर pane लिंक फ़ंक्शन में, addPane tabs नियंत्रक की केवल एक संपत्ति है, और यह केवल tabs कंट्रोलर ऑब्जेक्ट.डपैन है। तो फलक निर्देशक लिंकिंग फ़ंक्शन टैब नियंत्रक ऑब्जेक्ट तक पहुंच सकता है और इसलिए ऐडपेन विधि तक पहुंच सकता है।

मुझे उम्मीद है कि मेरी व्याख्या पर्याप्त स्पष्ट है .. यह समझाना मुश्किल है।


मैंने बस दोनों के बीच के अंतर पर एक सुंदर रोचक स्पष्टीकरण पढ़ा है, और नियंत्रकों को मॉडल संलग्न करने के लिए बढ़ती प्राथमिकता और नियंत्रक को दृश्य में बाध्य करने के लिए नियंत्रक को उपनाम दिया है। http://toddmotto.com/digging-into-angulars-controller-as-syntax/ लेख है। वह इसका जिक्र नहीं करता है लेकिन निर्देशों को परिभाषित करते समय, यदि आपको कई निर्देशों के बीच कुछ साझा करने की आवश्यकता है और एक सेवा नहीं चाहते हैं (वैध मामले हैं जहां सेवाएं परेशानी हैं) तो डेटा को मूल निर्देशक के नियंत्रक से संलग्न करें। $ स्कोप सेवा बहुत उपयोगी चीजें प्रदान करती है, $ सबसे स्पष्ट होने पर घड़ी देखते हैं, लेकिन अगर आपको डेटा को देखने के लिए डेटा को बाध्य करने की आवश्यकता है, तो टेम्पलेट में सादा नियंत्रक और 'नियंत्रक के रूप में' का उपयोग करना ठीक है, और तर्कसंगत रूप से बेहतर है।


कोणीय (पूर्व 1.0 आरसी) के पिछले संस्करणों ने आपको $ स्कोप विधि के साथ इस विनिमय के लिए उपयोग करने की अनुमति दी, लेकिन यह अब मामला नहीं है। इस दायरे पर परिभाषित विधियों के अंदर और $ स्कोप अदला-बदली करने योग्य हैं (कोणीय इसे $ स्कोप पर सेट करता है), लेकिन अन्यथा आपके नियंत्रक कन्स्ट्रक्टर के अंदर नहीं।

इस व्यवहार को वापस लाने के लिए (क्या किसी को पता है कि यह क्यों बदला गया था?) आप जोड़ सकते हैं:

return angular.extend($scope, this);

आपके नियंत्रक फ़ंक्शन के अंत में (बशर्ते कि $ नियंत्रक को इस नियंत्रक फ़ंक्शन में इंजेक्शन दिया गया हो)।

नियंत्रक ऑब्जेक्ट के माध्यम से अभिभावक के दायरे तक पहुंचने का इसका अच्छा प्रभाव पड़ता है जिसे आप बच्चे के साथ require: '^myParentDirective' प्राप्त कर सकते हैं require: '^myParentDirective'





this