Pertanyaan 'ini' vs $ scope di pengendali AngularJS


Dalam Bagian "Buat Komponen" di beranda AngularJS, ada contoh ini:

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);
  }
}

Perhatikan bagaimana select metode ditambahkan ke $scope, tetapi addPane metode ditambahkan ke this. Jika saya mengubahnya $scope.addPane, kode rusak.

Dokumentasi mengatakan bahwa sebenarnya ada perbedaan, tetapi tidak menyebutkan apa perbedaannya:

Versi sebelumnya dari Angular (pre 1.0 RC) memungkinkan Anda untuk menggunakannya this dipertukarkan dengan $scope metode, tetapi ini tidak lagi terjadi. Di dalam metode yang didefinisikan pada ruang lingkup this dan $scope dapat dipertukarkan (set sudut this untuk $scope), tetapi tidak sebaliknya di dalam konstruktor pengontrol Anda.

Bagaimana this dan $scope bekerja di pengontrol AngularJS?


965
2017-07-23 02:55


asal


Jawaban:


"Bagaimana this dan $scope bekerja di pengontrol AngularJS? "

Jawaban singkat:

  • this
    • Ketika fungsi konstruktor kontroler dipanggil, this adalah pengontrol.
    • Ketika suatu fungsi didefinisikan pada $scope objek disebut, this adalah "ruang lingkup yang berlaku saat fungsi dipanggil". Ini mungkin (atau mungkin tidak!) Menjadi $scope bahwa fungsi didefinisikan pada. Jadi, di dalam fungsi itu, this dan $scope mungkin tidak sama saja.
  • $scope
    • Setiap pengontrol memiliki kaitan $scope obyek.
    • Fungsi pengontrol (konstruktor) bertanggung jawab untuk mengatur properti model dan fungsi / perilaku pada yang terkait $scope.
    • Hanya metode yang ditentukan dalam hal ini $scope objek (dan objek induk lingkup, jika warisan prototipikal sedang dimainkan) dapat diakses dari HTML / tampilan. Mis., Dari ng-click, filter, dll.

Jawaban panjang:

Fungsi pengontrol adalah fungsi konstruktor JavaScript. Ketika fungsi konstruktor dijalankan (misalnya, ketika sebuah tampilan memuat), this (yaitu, "konteks fungsi") diatur ke objek pengontrol. Jadi dalam fungsi konstruktor kontroler "tab", ketika fungsi addPane dibuat

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

itu dibuat pada objek pengendali, bukan pada lingkup $. Tampilan tidak dapat melihat fungsi addPane - mereka hanya memiliki akses ke fungsi yang ditentukan pada lingkup $. Dengan kata lain, dalam HTML, ini tidak akan berfungsi:

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

Setelah fungsi konstruktor pengontrol "tab" dijalankan, kita memiliki yang berikut:

after tabs controller constructor function

Garis hitam putus-putus menunjukkan warisan prototipal - ruang isolasi yang secara prototip mewarisi Cakupan. (Ini tidak secara prototipis mewarisi dari ruang lingkup yang berlaku di mana arahan itu ditemui dalam HTML.)

Sekarang, fungsi tautan direktif panel ingin berkomunikasi dengan direktif tab (yang benar-benar berarti itu perlu mempengaruhi tab mengisolasi lingkup $ dalam beberapa cara). Acara dapat digunakan, tetapi mekanisme lain adalah memiliki direktif panel require pengontrol tab. (Tampaknya tidak ada mekanisme untuk direktif panel require tab $ scope.)

Jadi, ini menimbulkan pertanyaan: jika kita hanya memiliki akses ke pengendali tab, bagaimana kita mendapatkan akses ke tab mengisolasi $ scope (yang sebenarnya kita inginkan)?

Nah, garis putus-putus merah adalah jawabannya. The addPane () fungsi "lingkup" (Saya mengacu pada lingkup fungsi / penutupan JavaScript di sini) memberikan akses fungsi ke tab mengisolasi $ scope. Yaitu, addPane () memiliki akses ke "tab IsolateScope" pada diagram di atas karena penutupan yang dibuat ketika addPane () telah ditentukan. (Jika kita mendefinisikan addPane () pada objek tab $ scope, direktif panel tidak akan memiliki akses ke fungsi ini, dan karenanya tidak akan memiliki cara untuk berkomunikasi dengan tab $ scope.)

Untuk menjawab bagian lain dari pertanyaan Anda: how does $scope work in controllers?:

Dalam fungsi yang ditentukan pada lingkup $, this diatur ke "lingkup $ yang berlaku di mana / ketika fungsi dipanggil". Misalkan kita memiliki HTML berikut:

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

Dan itu ParentCtrl (Hanya) memiliki

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

Mengeklik tautan pertama akan menunjukkan itu this dan $scope sama, karena "ruang lingkup yang berlaku saat fungsi dipanggil"adalah ruang lingkup yang terkait dengan ParentCtrl.

Mengklik tautan kedua akan muncul this dan $scope adalah tidak sama, karena "ruang lingkup yang berlaku saat fungsi dipanggil"adalah ruang lingkup yang terkait dengan ChildCtrl. Jadi disini, this diatur ke ChildCtrl's $scope. Di dalam metode, $scope masih tetap ParentCtrl$ scope.

Biola

Saya mencoba untuk tidak menggunakan this di dalam fungsi yang didefinisikan pada $ scope, karena menjadi membingungkan ruang lingkup $ mana yang terpengaruh, terutama mengingat bahwa ng-repeat, ng-include, ng-switch, dan arahan semua bisa membuat lingkup anak sendiri.


949
2018-01-05 04:48



Alasan 'addPane' ditugaskan untuk ini adalah karena <pane> direktif.

Itu pane direktif tidak require: '^tabs', yang menempatkan objek pengendali tab dari arahan induk, ke fungsi tautan.

addPane ditugaskan untuk this supaya itu pane fungsi tautan bisa melihatnya. Kemudian di pane fungsi tautan, addPane hanyalah sebuah properti dari tabs pengontrol, dan itu hanya tabsControllerObject.addPane. Jadi fungsi menghubungkan panel directive dapat mengakses objek tab controller dan karena itu mengakses metode addPane.

Saya harap penjelasan saya cukup jelas ... agak sulit untuk dijelaskan.


50
2017-07-23 15:20



Saya baru saja membaca penjelasan yang cukup menarik tentang perbedaan antara keduanya, dan preferensi yang semakin meningkat untuk melampirkan model ke controller dan alias controller untuk mengikat model ke tampilan. http://toddmotto.com/digging-into-angulars-controller-as-syntax/ adalah artikelnya. Dia tidak menyebutkannya tetapi ketika menentukan arahan, jika Anda perlu berbagi sesuatu di antara beberapa arahan dan tidak menginginkan sebuah layanan (ada kasus sah di mana layanan merepotkan) kemudian lampirkan data tersebut ke pengontrol arahan induk. Layanan lingkup $ menyediakan banyak hal yang berguna, $ jam menjadi yang paling jelas, tetapi jika semua yang Anda butuhkan untuk mengikat data ke tampilan, menggunakan pengendali polos dan 'pengontrol sebagai' dalam template baik-baik saja, dan bisa dibilang lebih baik.


26
2017-08-28 21:25



Dalam kursus inihttps://www.codeschool.com/courses/shaping-up-with-angular-js) mereka menjelaskan cara menggunakan "ini" dan banyak hal lainnya.

Jika Anda menambahkan metode ke pengontrol melalui metode "ini", Anda harus memanggilnya dalam tampilan dengan nama kontroler "dot" properti atau metode Anda.

Misalnya menggunakan pengontrol Anda dalam tampilan Anda mungkin memiliki kode seperti ini:

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

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

    </div>

15
2017-09-24 07:29



Saya menyarankan Anda untuk membaca posting berikut: http://codetunnel.io/angularjs-controller-as-or-scope/

itu menggambarkan dengan sangat baik keuntungan menggunakan "Controller sebagai" untuk memaparkan variabel "$ scope".

Saya tahu Anda bertanya secara khusus tentang metode dan bukan variabel, tetapi saya pikir lebih baik tetap menggunakan satu teknik dan konsisten dengannya.

Jadi untuk pendapat saya, karena masalah variabel yang dibahas dalam posting, lebih baik untuk hanya menggunakan "Controller sebagai" teknik dan juga menerapkannya pada metode.


15
2017-11-03 10:31



Versi sebelumnya dari Angular (pre 1.0 RC) memungkinkan Anda untuk menggunakan ini   secara bergantian dengan metode $ scope, tetapi ini bukan lagi   kasus. Di dalam metode yang didefinisikan pada ruang lingkup ini dan ruang lingkup $ adalah   dapat dipertukarkan (seting sudut ini ke $ scope), tetapi tidak sebaliknya   di dalam konstruktor pengontrol Anda.

Untuk mengembalikan perilaku ini (apakah ada yang tahu mengapa itu diubah?) Anda dapat menambahkan:

return angular.extend($scope, this);

pada akhir fungsi pengontrol Anda (asalkan ruang lingkup $ disuntikkan ke fungsi pengontrol ini).

Ini memiliki efek yang bagus karena memiliki akses ke ruang lingkup orang tua melalui objek pengontrol yang dapat Anda dapatkan pada anak require: '^myParentDirective'


3
2018-06-20 08:46



$ scope memiliki 'ini' yang berbeda maka controller 'this'.Thus jika Anda meletakkan console.log (ini) di dalam controller itu memberi Anda objek (controller) dan this.addPane () menambahkan Metode addPane ke Objek controller. Tetapi ruang lingkup $ memiliki ruang lingkup yang berbeda dan semua metode dalam ruang lingkupnya perlu diakses oleh $ scope.methodName (). this.methodName() di dalam controller berarti menambahkan methos di dalam objek controller.$scope.functionName() dalam HTML dan di dalam

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

Tempel kode ini di editor Anda dan buka konsol untuk melihat ...

 <!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
2018-02-07 09:06