web-gelistirme-sc.com

'this', AngularJS denetleyicilerinde $ kapsamı

AngularJS'in ana sayfasının "Bileşen Oluştur" bölümünde , bu örnek var:

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 yönteminin $scope öğesine nasıl eklendiğine, ancak addPane yönteminin this öğesine eklendiğine dikkat edin. Onu $scope.addPane olarak değiştirirsem kod kırılır.

Belgeler aslında orada bir fark olduğunu söylüyor, ancak aradaki farkın ne olduğunu söylemiyor:

Daha önceki Angular sürümleri (1.0 öncesi RC), $scope yöntemiyle this işlevini birbirinin yerine kullanmanıza izin verdi, ancak bu artık böyle değil. this ve $scope kapsamında tanımlanan yöntemlerin içinde değiştirilebilir (açısal ayarlar this ila $scope) değiştirilebilir, ancak denetleyici yapıcınızın içinde değil.

AngularJS denetleyicilerinde this ve $scope nasıl çalışır?

987
Alexei Boronine

"thisve $scope AngularJS denetleyicilerinde nasıl çalışır?"

Kısa cevap :

  • thisname __
    • Denetleyici yapıcı işlevi çağrıldığında, denetleyici, thisişlevidir.
    • $scope nesnesinde tanımlanan bir işlev çağrıldığında, thisname__, "işlev çağrıldığında geçerli olan kapsam" dır. Bu, fonksiyonun tanımlandığı $scope olabilir (veya olmayabilir!). Böylece, fonksiyon içinde thisve $scope may not aynı olabilir.
  • $scope
    • Her denetleyicinin ilişkili bir $scope nesnesi vardır.
    • Bir denetleyici (yapıcı) işlevi, ilgili $scope üzerindeki model özelliklerini ve işlevlerini/davranışını ayarlamaktan sorumludur.
    • Yalnızca bu $scope nesnesinde (ve prototipik miras devrede ise ana kapsam nesneleri) tanımlanan yöntemlere HTML/görünümden erişilebilir. Örneğin, ng-click, filtreler vb.

Uzun cevap :

Bir denetleyici işlevi bir JavaScript yapıcı işlevidir. Yapıcı işlevi yürütüldüğünde (örneğin, bir görünüm yüklendiğinde), this(yani, "işlev bağlamı") denetleyici nesnesine ayarlanır. Yani "sekmeler" denetleyici yapıcı işlevi, addPane işlevi oluşturulduğunda

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

denetleyici nesnesinde oluşturulur, $ kapsamı üzerinde değil. Görünümler addPane işlevini göremez - yalnızca $ kapsamında tanımlanan işlevlere erişebilirler. Başka bir deyişle, HTML’de bu işe yaramaz:

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

"Sekmeler" denetleyici yapıcı işlevi yürütüldükten sonra aşağıdakilere sahibiz:

after tabs controller constructor function

Kesikli siyah çizgi prototip mirasını gösterir - prototipik olarak Scope 'dan miras alan bir izolatik kapsamdır. (Yönergenin HTML’de karşılaştığı geçerli kapsamdan prototipik olarak devralmaz.)

Şimdi, bölme yönergesinin link işlevi, yönerge yönergesi ile iletişim kurmak istiyor (bu da gerçekten $ sekmeleri izole eden sekmeleri etkilemesi gerektiği anlamına geliyor). Olaylar kullanılabilir, ancak başka bir mekanizma da sekme denetleyicisinin requirebölmesi direktifine sahip olmasıdır. (Bölme yönergesinin require$ $ sekmelerine yönelik bir mekanizması yoktur.)

Öyleyse, bu soruyu sorgular: eğer sadece sekme denetleyicisine erişimimiz varsa, $ kapsamı izole eden sekmelere nasıl erişebiliriz (gerçekte istediğimiz budur)?

Eh, kırmızı noktalı çizgi cevaptır. AddPane () işlevinin "kapsamı" (burada JavaScript'in işlev kapsamı/kapanışlarına atıfta bulunuyorum), işleve $ kapsamını izole eden sekmelere erişim sağlar. Örneğin, addPane (), addPane () tanımlandığında oluşturulan bir kapatma nedeniyle yukarıdaki şemada "IsolateScope" sekmelerine erişime sahiptir. (Yerine $ kapsam nesnesi üzerinde addPane () tanımlıyorsak, bölme yönergesi bu işleve erişemez ve bu nedenle $ kapsamı sekmeleri ile iletişim kurmanın bir yolu olmazdı.)

Sorunuzun diğer bölümünü yanıtlamak için: how does $scope work in controllers?:

$ Kapsamı içinde tanımlanmış fonksiyonlar içinde, thisname__, "fonksiyonun çağrıldığı/olduğu zaman geçerli olan $ kapsamı" olarak ayarlanır. Aşağıdaki HTML koduna sahip olduğumuzu varsayalım:

<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>

Ve ParentCtrl(Yalnızca)

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

İlk bağlantıya tıklamak thisve $scope'in aynı olduğunu gösterecektir, çünkü "işlev çağrıldığında geçerli kapsam" ParentCtrlile ilişkilendirilmiş kapsamdır.

İkinci bağlantıya tıkladığınızda thisve $scope are not aynı olacaktır, çünkü "işlev çağrıldığında geçerli kapsam" ChildCtrlile ilişkili kapsam. Yani burada, thisChildCtrlname __ 'in $scope olarak ayarlanmıştır. Yöntemin içinde, $scope, hala ParentCtrlname __ 'nin $ kapsamıdır.

Keman

$ Kapsamında tanımlanan bir fonksiyonun içinde thiskullanmaya çalışıyorum, çünkü hangi $ kapsamının etkilendiğini karıştırıyor, özellikle ng-repeat, ng-include, ng-switch ve direktiflerinin hepsinin kendi çocuk kapsamlarını yaratabileceğini düşünüyoruz. .

985
Mark Rajcok

'AddPane' öğesinin atanmasının nedeni <pane> yönergesinden kaynaklanmaktadır.

pane yönergesi, tab denetleyicisi nesnesini bir üst yönergeden link işlevine yerleştiren require: '^tabs' işlevini kullanır.

addPane, this öğesine atanır, böylece pane link işlevi bunu görebilir. Sonra pane link işlevinde addPane, tabs denetleyicisinin yalnızca bir özelliğidir ve sadece tabsControllerObject.addPane sekmesidir. Böylece bölme direktifinin bağlanma işlevi sekmeler denetleyici nesnesine erişebilir ve böylece addPane yöntemine erişebilir.

Umarım açıklamam yeterince açıktır .. açıklaması biraz zor.

53
Andrew Joslin

Ben sadece ikisi arasındaki fark hakkında oldukça ilginç bir açıklama okudum ve denetleyiciye model eklemek için artan tercih ve modelleri görünüme bağlamak için denetleyicinin diğer adı. http://toddmotto.com/digging-into-angulars-controller-as-syntax/ makaledir. Bundan bahsetmiyor, ancak direktifleri tanımlarken, birden fazla direktif arasında bir şeyi paylaşmanız gerekiyorsa ve bir servis istemiyorsanız (servislerin zorlaştığı meşru durumlar vardır), ardından verileri ana direktifin kontrolörüne ekleyin. $ Kapsamı hizmeti çok yararlı şeyler sunar, $ watch en açık olanıdır, ancak şablona düz denetleyiciyi ve 'denetleyiciyi' kullanarak düz ve denetleyici kullanarak veriyi bağlamanız gerekiyorsa, tercih edilebilir.

26
Derek

Aşağıdaki yazıyı okumanı tavsiye ederim: AngularJS: "Denetleyici" veya "$ kapsam"?

Değişkenleri "$ kapsamı" ndan ortaya çıkarmak için "Denetleyici" olarak kullanılmasının avantajlarını çok iyi açıklar.

Değişkenleri değil, özellikle yöntemleri sorduğunuzu biliyorum, ancak bir tekniğe bağlı kalmanın ve bununla tutarlı olmanın daha iyi olacağını düşünüyorum. 

Bu yüzden benim görüşüme göre, postta tartışılan değişkenler sorunu nedeniyle, sadece "Controller" olarak tekniğin kullanılması ve aynı zamanda yöntemlerin uygulanması daha iyidir.

18
Liran Brimer

Bu derste ( https://www.codeschool.com/courses/shaping-up-with-angular-js ) "bu" ve diğer pek çok şeyin nasıl kullanılacağını açıklarlar.

"This" yöntemi ile denetleyiciye bir yöntem eklerseniz, özellik veya yönteminizi denetleyicinin adı "nokta" olan görünümde çağırmanız gerekir.

Örneğin, görünümünüzü denetleyicinizi kullanarak aşağıdaki gibi bir kodunuz olabilir:

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

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

    </div>
15
Sandro

Daha önceki Angular sürümleri (pre 1.0 RC) bunu kullanmanıza izin verdi. $ kapsamı yöntemiyle değiştirilebilir, ancak bu artık vaka. Kapsamda tanımlanan yöntemlerin içinde bu ve $ kapsamı değiştirilebilir (açısal bunu $ kapsamına ayarlar), ancak aksi durumda yok. denetleyici yapıcınızın içinde.

Bu davranışı geri getirmek için (neden değiştirildiğini bilen var mı?)

return angular.extend($scope, this);

denetleyici işlevinizin sonunda (bu denetleyici işlevine $ kapsamı girilmişse).

Bu, require: '^myParentDirective' ile alt öğesinde bulabileceğiniz denetleyici nesnesi aracılığıyla üst kapsama erişime sahip olmanın hoş bir etkiye sahiptir

3
Kamil Szot

$ kapsamı farklı bir 'this', sonra kontrolör 'this'. Eğer bir console.log (this) kontrolörün içine koyarsanız, size bir nesne (kontrolör) verir ve this.addPane () kontrolör Nesnesine addPane Yöntemi ekler. Ancak $ kapsamı farklı kapsamı vardır ve kapsamındaki tüm yöntemlerin $ kapsamına göre olması gerekir.ethodName () .this.methodName() controller__ içindeki __ işlevini denetleyici nesnesi eklemek anlamına gelir .$scope.functionName(), HTML'de ve içinde 

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

Editörünüze bu kodu yapıştırın ve açmak için konsolu açın ...

 <!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>
0
Aniket Jha