$ apply () dan $ digest () adalah dua konsep inti di AngularJS, tetapi kadang -kadang membingungkan. Untuk memahami cara kerja AngularJS, pertama -tama Anda perlu memahami bagaimana $ apply () dan $ digest () bekerja. Artikel ini bertujuan untuk menjelaskan apa $ apply () dan $ digest (), dan bagaimana mereka diterapkan dalam penyandian sehari -hari.
1. Jelajahi $ apply () dan $ digest ()
1.1. Memahami pengikatan data dua arah dan $ watch ();
AngularJS menyediakan fitur yang sangat keren yang disebut pengikatan data dua arah, yang sangat menyederhanakan bagaimana kami menulis kode kami. Ikatan data berarti bahwa ketika setiap data dalam tampilan berubah, perubahan akan secara otomatis diumpankan kembali ke data lingkup, yang berarti bahwa model ruang lingkup akan diperbarui secara otomatis. Demikian pula, ketika model lingkup berubah, data dalam tampilan diperbarui ke nilai terbaru. Jadi bagaimana cara AngularJS melakukan ini? Saat Anda menulis ekspresi seperti {{AmoDel}}, AngularJS akan mengatur pengamat untuk Anda pada model lingkup, yang digunakan untuk memperbarui tampilan saat data berubah. Pengamat di sini sama dengan pengamat yang akan Anda atur di AngularJS:
$ scope. $ watch ('amodel', function (newValue, oldvalue) {// perbarui dom dengan newValue});Parameter kedua diteruskan ke $ watch () adalah fungsi callback, yang akan dipanggil ketika nilai amodel berubah. Ketika Amodel berubah, tidak sulit untuk memahami bahwa fungsi panggilan balik ini akan dipanggil untuk memperbarui tampilan, tetapi masih ada masalah yang sangat penting! Bagaimana AngularJS tahu kapan harus memanggil fungsi panggilan balik ini? Dengan kata lain, bagaimana AngularJS menyebut fungsi panggilan balik yang sesuai ketika mengetahui bahwa Amodel telah berubah? Apakah akan menjalankan fungsi secara berkala untuk memeriksa apakah data dalam model lingkup telah berubah? Nah, di situlah $ Digest Loop masuk.
Di Loop $ Digest, Watchers akan dipecat. Ketika seorang pengamat dipicu, AngularJS akan mendeteksi model lingkup. Jika berubah, fungsi panggilan balik yang terkait dengan pengamat akan dipanggil. Jadi, pertanyaan berikutnya adalah kapan loop $ digest dimulai dengan berbagai cara?
Setelah menelepon $ scope. $ Digest (), loop $ digest dimulai. Misalkan Anda mengubah data dalam ruang lingkup dalam fungsi penangan yang sesuai dengan arahan klik ng, AngularJS akan secara otomatis memicu loop $ digest dengan memanggil $ digest (). Ketika Loop $ Digest dimulai, ia memicu setiap pengamat. Pengamat ini akan memeriksa apakah nilai model saat ini dalam ruang lingkup berbeda dari nilai model yang dihitung terakhir kali. Jika berbeda, fungsi panggilan balik yang sesuai akan dieksekusi. Hasil memanggil fungsi ini adalah bahwa konten ekspresi dalam tampilan (catatan penerjemah: seperti {{amodel}}) akan diperbarui. Selain arahan klik ng, ada beberapa arahan dan layanan bawaan lainnya untuk memungkinkan Anda mengubah model (seperti NG-model, $ timeout, dll.) Dan secara otomatis memicu loop $ digest.
Sejauh ini tidak buruk! Namun, ada masalah kecil. Dalam contoh di atas, AngularJS tidak memanggil $ digest () secara langsung, tetapi memanggil $ scope. $ Apply (), yang memanggil $ rootscope. $ Digest (). Oleh karena itu, loop $ digest dimulai dari $ Rootscope, yang kemudian akan mengakses semua pengamat lingkup anak -anak.
Catatan: $ scope. $ Apply () akan secara otomatis menelepon $ rootscope. $ Digest ().
Metode $ Apply () memiliki dua bentuk:
Yang pertama akan menerima fungsi sebagai parameter, menjalankan fungsi dan memicu loop $ Digest.
Tipe kedua tidak akan menerima parameter apa pun dan hanya memicu loop $ digest. Kita akan segera lihat mengapa bentuk pertama lebih baik.
1.2. Kapan secara manual memanggil metode $ apply ()?
Jika AngularJS selalu membungkus kode kami ke dalam suatu fungsi dan lulus dalam $ apply () untuk memulai loop $ digest, lalu kapan kita perlu memanggil metode $ apply () secara manual? Faktanya, AngularJS memiliki persyaratan yang sangat jelas untuk ini, bahwa ia hanya bertanggung jawab untuk secara otomatis menanggapi perubahan yang terjadi dalam konteks AngularJS (mis., Perubahan pada model yang terjadi dalam metode $ Apply ()). Beginilah arahan bawaan AngularJS melakukannya, sehingga perubahan model apa pun akan tercermin dalam tampilan. Namun, jika Anda memodifikasi model di mana saja di luar konteks AngularJS, Anda perlu memberi tahu AngularJS dengan menelepon $ apply () secara manual. Ini seperti memberi tahu AngularJS bahwa Anda telah memodifikasi beberapa model dan berharap bahwa AngularJ dapat membantu Anda memicu pengamat untuk merespons dengan benar.
Misalnya, jika Anda menggunakan setTimeout () di JavaScript untuk memperbarui model lingkup, maka AngularJS tidak memiliki cara untuk mengetahui apa yang telah Anda ubah. Dalam hal ini, adalah tanggung jawab Anda untuk memanggil $ apply (), dan memicu loop $ digest dengan memanggilnya. Demikian pula, jika Anda memiliki arahan untuk mengatur pendengar acara DOM dan memodifikasi beberapa model dalam pendengar itu, Anda juga perlu memanggil $ apply () secara manual untuk memastikan bahwa perubahan akan tercermin dengan benar dalam tampilan.
Mari kita lihat sebuah contoh. Bergabunglah Anda memiliki halaman yang setelah halaman dimuat, Anda ingin menampilkan pesan setelah dua detik. Implementasi Anda mungkin terlihat seperti ini:
html:
<body ng-app = "myapp"> <div ng-controller = "messageController"> pesan tertunda: {{pesan}} </div> </body>Javascript:
/ * Apa yang terjadi tanpa $ apply () */ angular.module ('myapp', []). Controller ('messageController', function ($ scope) {$ scope.getMessage = function () {setTimeout (function () {$ scope.message = 'fetched setelah 3 detik; console.log () {$ scope. } $ scope.getMessage ();});Dengan menjalankan contoh ini, Anda akan melihat bahwa setelah dua detik, konsol memang menampilkan model yang diperbarui, namun, tampilan tidak diperbarui. Mungkin Anda sudah tahu alasannya, yaitu, kami lupa memanggil metode $ apply (). Oleh karena itu, kita perlu memodifikasi getMessage () sebagai berikut:
/ * Apa yang terjadi dengan $ apply */angular.module ('myapp', []). Controller ('messageController', function ($ scope) {$ scope.getMessage = function () {setTimeout (function () {$ scope. $ Apply (function () {// wrapped ini di dalam $ scope.mess. $ scope.message);Jika Anda menjalankan contoh di atas, Anda akan melihat bahwa tampilan juga akan diperbarui setelah dua detik. Satu -satunya perubahan adalah bahwa kode kami sekarang dibungkus menjadi $ scope. $ Apply (), yang secara otomatis akan memicu $ rootscope. $ Digest (), sehingga pengamat dipicu untuk memperbarui tampilan.
Catatan: Ngomong -ngomong, Anda harus menggunakan layanan $ timeout alih -alih setTimeout (), karena yang pertama akan menghubungi $ apply () untuk Anda, jadi Anda tidak perlu memanggilnya secara manual.
Juga, perhatikan bahwa dalam kode di atas, Anda juga dapat secara manual menghubungi $ apply () tanpa parameter setelah memodifikasi model, seperti halnya berikut:
$ scope.getMessage = function () {setTimeOut (function () {$ scope.message = 'diambil setelah dua detik'; console.log ('pesan:' + $ scope.message); $ scope. $ apply (); // ini memicu $ digest}, 2000); };Kode di atas menggunakan bentuk kedua dari $ apply (), yaitu formulir tanpa parameter. Penting untuk diingat bahwa Anda harus selalu menggunakan metode $ Apply () yang mengambil fungsi sebagai parameter. Ini karena ketika Anda melewati fungsi ke $ apply (), fungsi akan dibungkus menjadi blok cobalah ... Catch, jadi setelah pengecualian terjadi, pengecualian akan diproses oleh layanan $ ExceptionHandler.
Situasi menggunakan $ apply () adalah sebagai berikut:
• Anda biasanya dapat menghubungi $ apply () berdasarkan arahan apa pun yang disediakan oleh Angular yang dapat digunakan dalam tampilan. Semua arahan NG- [acara] (seperti NG-klik, NG-Keypress) akan menghubungi $ apply ().
• Selain itu, Anda juga dapat mengandalkan serangkaian layanan bawaan sudut untuk menghubungi $ digest (). Misalnya, layanan $ http akan menghubungi $ apply () setelah permintaan XHR selesai dan nilai pengembalian pembaruan dipicu.
• Setiap kali kami menangani acara secara manual, menggunakan kerangka kerja pihak ketiga (seperti jQuery, Facebook API), atau panggilan setTimeout (), kami dapat menggunakan fungsi $ Apply () untuk membuat Angular Return A $ Digest Loop.
Hubungi SetTimeOut ():
<! Doctype html> <html ng-app = "myapp"> <head> <itement> $ scope. $ Apply () penggunaan </title> <meta charset = "utf-8"> <script src = "http:/appulars id = "Div1" ng-controller = "myText"> <verv> {{text}} </div> <input id = "btn" type = "tombol" value = "jQuery-event"> </input> </div> </body> </html> <script type = "javascript ') </body = </html> <script type =" javascript ") </body = </html> <skrip type =" javascript ") </body = </html> <script type =" javascript ") </body </html> <script type =" text/javascript ") </body = MyAplcript = mycript = mycript = mycript = mycript = mycript"> var. myModule.controller ("myText", function ($ scope) {$ scope.text = "place"; setTimeout (function () {$ scope.text = "Nilai diselesaikan setelah waktu keluar"; $ scope. $ apply (); // deteksi nilai kotor)))));} (jika tidak data tidak dapat disegarkan ke antarmuka (); // deteksi nilai kotor))))); jika tidak data tidak dapat disegarkan ke antarmuka (); </script>Gunakan kerangka kerja pihak ketiga (seperti jQuery, Facebook API):
<! Doctype html> <html ng-app = "myApp"> <head> <itement> $ scope. $ Apply () penggunaan </iteme> <meta charset = "utf-8"> <script src = "https://cdn.jsdelivr.net/jQuery/3.1.1.m. src = "http://apps.bdimg.com/libs/angular.js/1.4.6/angular.min.js"> </script> <body> <v id = "div1" ng-controller = "mytext"> <v> {{text}} </div> <input iD = " value = "jQuery-event"> </input> </div> </body> </html> <script type = "text/javascript"> var mymodule = angular.module ('myapp', []); mymodule.controller ("myText", function ($ scope) {$ scope.text = "place";}); $ (function () {$ ("#btn"). Klik (function () {var $ scope = $ ("#btn"). scope (); $ scope.text = "Nilai disetel dalam jQuery"; $ scope. $ apply ();});}) </script>1.3. Berapa kali loop $ digest berjalan?
Ketika Loop $ Digest berjalan, Watchers akan dieksekusi untuk memeriksa apakah model dalam ruang lingkup telah berubah. Jika perubahan terjadi, fungsi pendengar yang sesuai akan dieksekusi. Ini melibatkan masalah penting. Bagaimana jika fungsi pendengar itu sendiri akan memodifikasi model lingkup? Bagaimana AngularJs menangani situasi ini?
Jawabannya adalah bahwa Loop $ Digest tidak akan berjalan hanya sekali. Setelah loop saat ini berakhir, ia akan menjalankan loop lain untuk memeriksa apakah model telah berubah. Ini adalah pemeriksaan kotor, yang digunakan untuk menangani perubahan model yang mungkin terjadi ketika fungsi pendengar dieksekusi. Oleh karena itu, Loop $ Digest akan terus berjalan sampai model tidak lagi berubah, atau Loop $ Digest mencapai 10 kali. Oleh karena itu, cobalah untuk tidak memodifikasi model dalam fungsi pendengar sebanyak mungkin.
Catatan: Loop $ Digest juga akan berjalan setidaknya dua kali, bahkan jika tidak ada model yang diubah dalam fungsi pendengar. Seperti dibahas di atas, itu akan berjalan sekali lagi untuk memastikan bahwa model tidak berubah.
Kesimpulan
Yang paling penting untuk diingat adalah apakah AngularJS dapat mendeteksi modifikasi Anda pada model. Jika tidak dapat dideteksi, maka Anda perlu menghubungi $ apply () secara manual.
Jika Anda memiliki pertanyaan, silakan tinggalkan saya pesan dan editor akan membalas semua orang tepat waktu. Terima kasih banyak atas dukungan Anda ke situs web Wulin.com!