Dengan kotor memeriksa $scopeobjek
Angular mempertahankan arraypengamat sederhana di $scopeobjek. Jika Anda memeriksa setiap $scopeAnda akan menemukan bahwa itu berisi arraydisebut $$watchers.
Setiap pengamat adalah objectyang berisi antara lain
- Ekspresi yang diawasi oleh pengamat. Ini mungkin hanya
attributenama, 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
$scopesebagai kotor.
- Suatu fungsi yang akan dieksekusi jika pengamat kotor.
Bagaimana pengamat didefinisikan
Ada banyak cara untuk mendefinisikan pengamat di AngularJS.
Anda secara eksplisit dapat $watchsebuah attributeon $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-modeluntuk menentukan pengamat untuk Anda.
<input ng-model="person.username" />
The $digestsiklus 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 $scopedan semua anak-anaknya . Untuk masing-masing $scope object, kami mengulanginya $$watchers arraydan 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, $scopeitu kotor
Jika pengamat dipicu, aplikasi tahu ada sesuatu yang berubah, dan $scopeditandai sebagai kotor.
Fungsi pengamat dapat mengubah atribut lainnya pada $scopeatau pada induknya $scope. Jika satu $watcherfungsi telah dipicu, kami tidak dapat menjamin bahwa fungsi kami yang lain $scopemasih bersih, jadi kami menjalankan seluruh siklus intisari lagi.
Ini karena AngularJS memiliki ikatan dua arah, sehingga data dapat dilewatkan kembali ke $scopepohon. Kami dapat mengubah nilai pada yang lebih tinggi $scopeyang telah dicerna. Mungkin kami mengubah nilai pada $rootScope.
Jika $digestkotor, kami menjalankan seluruh $digestsiklus lagi
Kami terus-menerus mengulangi $digestsiklus hingga siklus digest muncul bersih (semua $watchekspresi 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 $scopehierarki 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-repeatmelebihi besar JSON arraymisalnya. 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 $scopepohon 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-repeatbanyak item.
<div ng-repeat="person in people track by username">
{{::person.username}}
</div>