Dengan kotor memeriksa $scope
objek
Angular mempertahankan array
pengamat sederhana di $scope
objek. Jika Anda memeriksa setiap $scope
Anda akan menemukan bahwa itu berisi array
disebut $$watchers
.
Setiap pengamat adalah object
yang berisi antara lain
- Ekspresi yang diawasi oleh pengamat. Ini mungkin hanya
attribute
nama, atau sesuatu yang lebih rumit.
- Nilai ekspresi terakhir yang diketahui. Ini dapat diperiksa terhadap nilai ekspresi yang dihitung saat ini. Jika nilainya berbeda, pengamat akan memicu fungsi dan menandai
$scope
sebagai kotor.
- Suatu fungsi yang akan dieksekusi jika pengamat kotor.
Bagaimana pengamat didefinisikan
Ada banyak cara untuk mendefinisikan pengamat di AngularJS.
Anda secara eksplisit dapat $watch
sebuah attribute
on $scope
.
$scope.$watch('person.username', validateUnique);
Anda dapat menempatkan {{}}
interpolasi di template Anda (pengamat akan dibuat untuk Anda saat ini $scope
).
<p>username: {{person.username}}</p>
Anda dapat meminta arahan seperti ng-model
untuk menentukan pengamat untuk Anda.
<input ng-model="person.username" />
The $digest
siklus memeriksa semua pengamat terhadap nilai terakhir mereka
Ketika kita berinteraksi dengan AngularJS melalui saluran normal (ng-model, ng-repeat, dll) siklus digest akan dipicu oleh arahan.
Sebuah siklus intisari adalah traversal pertama-utama dari $scope
dan semua anak-anaknya . Untuk masing-masing $scope
object
, kami mengulanginya $$watchers
array
dan mengevaluasi semua ekspresi. Jika nilai ekspresi baru berbeda dari nilai terakhir yang diketahui, fungsi pengamat disebut. Fungsi ini dapat mengkompilasi ulang bagian DOM, mengkompilasi ulang nilai pada $scope
, memicu AJAX
request
, apa pun yang Anda perlu lakukan.
Setiap ruang lingkup dilalui dan setiap ekspresi arloji dievaluasi dan diperiksa terhadap nilai terakhir.
Jika seorang pengamat dipicu, $scope
itu kotor
Jika pengamat dipicu, aplikasi tahu ada sesuatu yang berubah, dan $scope
ditandai sebagai kotor.
Fungsi pengamat dapat mengubah atribut lainnya pada $scope
atau pada induknya $scope
. Jika satu $watcher
fungsi telah dipicu, kami tidak dapat menjamin bahwa fungsi kami yang lain $scope
masih bersih, jadi kami menjalankan seluruh siklus intisari lagi.
Ini karena AngularJS memiliki ikatan dua arah, sehingga data dapat dilewatkan kembali ke $scope
pohon. Kami dapat mengubah nilai pada yang lebih tinggi $scope
yang telah dicerna. Mungkin kami mengubah nilai pada $rootScope
.
Jika $digest
kotor, kami menjalankan seluruh $digest
siklus lagi
Kami terus-menerus mengulangi $digest
siklus hingga siklus digest muncul bersih (semua $watch
ekspresi memiliki nilai yang sama seperti pada siklus sebelumnya), atau kami mencapai batas digest. Secara default, batas ini ditetapkan 10.
Jika kami mencapai batas cerna, AngularJS akan memunculkan kesalahan di konsol:
10 $digest() iterations reached. Aborting!
Intisnya keras pada mesin tetapi mudah pada pengembang
Seperti yang Anda lihat, setiap kali ada perubahan dalam aplikasi AngularJS, AngularJS akan memeriksa setiap pengamat tunggal dalam $scope
hierarki untuk melihat bagaimana merespons. Untuk pengembang, ini adalah anugerah produktivitas besar, karena Anda sekarang perlu menulis hampir tidak ada kode pengkabelan, AngularJS hanya akan melihat jika suatu nilai telah berubah, dan membuat aplikasi lainnya konsisten dengan perubahan tersebut.
Dari perspektif mesin, ini sangat tidak efisien dan akan memperlambat aplikasi kita jika kita membuat terlalu banyak pengamat. Misko telah mengutip angka sekitar 4000 pengamat sebelum aplikasi Anda terasa lambat di peramban yang lebih lama.
Batas ini mudah dijangkau jika Anda ng-repeat
melebihi besar JSON
array
misalnya. Anda dapat mengurangi ini dengan menggunakan fitur-fitur seperti ikatan satu kali untuk mengkompilasi template tanpa membuat pengamat.
Cara menghindari membuat terlalu banyak pengamat
Setiap kali pengguna Anda berinteraksi dengan aplikasi Anda, setiap pengamat tunggal di aplikasi Anda akan dievaluasi setidaknya satu kali. Sebagian besar mengoptimalkan aplikasi AngularJS adalah mengurangi jumlah pengamat di $scope
pohon Anda . Salah satu cara mudah untuk melakukan ini adalah dengan mengikat satu kali .
Jika Anda memiliki data yang jarang berubah, Anda hanya dapat mengikatnya sekali menggunakan :: sintaks, seperti:
<p>{{::person.username}}</p>
atau
<p ng-bind="::person.username"></p>
Ikatan hanya akan dipicu ketika template yang berisi diberikan dan data dimasukkan $scope
.
Ini sangat penting ketika Anda memiliki ng-repeat
banyak item.
<div ng-repeat="person in people track by username">
{{::person.username}}
</div>