Bagaimana cara kerja pengikatan data dalam AngularJS
kerangka kerja?
Saya belum menemukan detail teknis di situs mereka . Lebih atau kurang jelas cara kerjanya saat data disebarkan dari tampilan ke model. Tetapi bagaimana AngularJS melacak perubahan properti model tanpa setter dan getter?
Saya menemukan bahwa ada pengamat JavaScript yang dapat melakukan pekerjaan ini. Tetapi mereka tidak didukung di Internet Explorer 6 dan Internet Explorer 7 . Jadi, bagaimana AngularJS tahu bahwa saya mengubah misalnya berikut ini dan mencerminkan perubahan ini pada pandangan?
myobject.myproperty="new value";
javascript
angularjs
data-binding
Pashec
sumber
sumber
Jawaban:
AngularJS mengingat nilai dan membandingkannya dengan nilai sebelumnya. Ini adalah pengecekan kotor dasar. Jika ada perubahan nilai, maka ini akan mengaktifkan perubahan acara.
The
$apply()
metode, yang adalah apa yang Anda sebut ketika Anda transisi dari dunia non-AngularJS ke dunia AngularJS, panggilan$digest()
. Intisari hanyalah pengecekan kotor lama. Ini bekerja di semua browser dan benar-benar dapat diprediksi.Membandingkan pengecekan kotor (AngularJS) vs pendengar perubahan ( KnockoutJS dan Backbone.js ): Walaupun pemeriksaan kotor mungkin tampak sederhana, dan bahkan tidak efisien (saya akan membahasnya nanti), ternyata secara semantik benar sepanjang waktu, sementara perubahan pendengar memiliki banyak kasus sudut aneh dan membutuhkan hal-hal seperti pelacakan ketergantungan untuk membuatnya lebih semantik. Pelacakan ketergantungan KnockoutJS adalah fitur cerdas untuk masalah yang tidak dimiliki AngularJS.
Masalah dengan pendengar perubahan:
Bagaimana dengan kinerja?
Jadi sepertinya kita lambat, karena pemeriksaan kotor tidak efisien. Di sinilah kita perlu melihat bilangan real daripada hanya memiliki argumen teoretis, tetapi pertama-tama mari kita mendefinisikan beberapa kendala.
Manusia adalah:
Lambat - Apa pun yang lebih cepat dari 50 ms tidak terlihat oleh manusia dan karenanya dapat dianggap sebagai "instan".
Terbatas - Anda tidak dapat benar-benar menampilkan lebih dari sekitar 2.000 informasi kepada manusia pada satu halaman. Lebih dari itu UI yang benar-benar buruk, dan manusia toh tidak bisa memproses ini.
Jadi pertanyaan sebenarnya adalah ini: Berapa banyak perbandingan yang dapat Anda lakukan pada browser dalam 50 ms? Ini adalah pertanyaan yang sulit dijawab karena banyak faktor yang ikut bermain, tetapi ini adalah ujian: http://jsperf.com/angularjs-digest/6 yang menciptakan 10.000 pengamat. Pada peramban modern ini hanya membutuhkan waktu di bawah 6 ms. Di Internet Explorer 8 dibutuhkan sekitar 40 ms. Seperti yang Anda lihat, ini bukan masalah bahkan di browser lambat hari ini. Ada peringatan: perbandingan harus sederhana agar sesuai dengan batas waktu ... Sayangnya itu terlalu mudah untuk menambahkan perbandingan lambat ke AngularJS, sehingga mudah untuk membangun aplikasi lambat ketika Anda tidak tahu apa yang Anda sedang melakukan. Tetapi kami berharap memiliki jawaban dengan menyediakan modul instrumentasi, yang akan menunjukkan kepada Anda perbandingan mana yang lambat.
Ternyata video game dan GPU menggunakan pendekatan pengecekan kotor, khususnya karena konsisten. Selama mereka melewati kecepatan refresh monitor (biasanya 50-60 Hz, atau setiap 16,6-20 ms), kinerja apa pun yang merupakan pemborosan, jadi Anda lebih baik menggambar lebih banyak barang, daripada mendapatkan FPS lebih tinggi.
sumber
Misko sudah memberikan deskripsi yang sangat baik tentang bagaimana data binding bekerja, tetapi saya ingin menambahkan pandangan saya tentang masalah kinerja dengan pengikatan data.
Seperti yang dikatakan Misko, sekitar 2000 binding adalah tempat Anda mulai melihat masalah, tetapi Anda seharusnya tidak memiliki lebih dari 2000 informasi di satu halaman. Ini mungkin benar, tetapi tidak semua pengikatan data terlihat oleh pengguna. Setelah Anda mulai membangun segala jenis widget atau kisi data dengan pengikatan dua arah, Anda dapat dengan mudah menekan 2.000 binding, tanpa memiliki UX yang buruk.
Pertimbangkan, misalnya, kotak kombo tempat Anda bisa mengetik teks untuk memfilter opsi yang tersedia. Kontrol semacam ini dapat memiliki ~ 150 item dan masih bisa digunakan. Jika memiliki beberapa fitur tambahan (misalnya kelas tertentu pada opsi yang dipilih saat ini) Anda mulai mendapatkan 3-5 binding per opsi. Letakkan tiga widget ini di halaman (mis. Satu untuk memilih negara, yang lain untuk memilih kota di negara tersebut, dan yang ketiga untuk memilih hotel) dan Anda sudah berada di antara 1.000 dan 2000 binding.
Atau pertimbangkan kisi-kisi data dalam aplikasi web perusahaan. 50 baris per halaman tidak masuk akal, yang masing-masing dapat memiliki 10-20 kolom. Jika Anda membangun ini dengan ng-repeat, dan / atau memiliki informasi dalam beberapa sel yang menggunakan beberapa binding, Anda bisa mendekati 2000 binding dengan grid ini saja.
Saya menemukan ini menjadi masalah besar ketika bekerja dengan AngularJS, dan satu-satunya solusi yang saya dapat temukan sejauh ini adalah membangun widget tanpa menggunakan penjilidan dua arah, alih-alih menggunakan ngOnce, pengamat deregistering dan trik serupa, atau konstruk arahan yang membangun DOM dengan manipulasi jQuery dan DOM. Saya merasa ini mengalahkan tujuan menggunakan Angular di tempat pertama.
Saya ingin mendengar saran tentang cara lain untuk menangani hal ini, tetapi mungkin saya harus menulis pertanyaan saya sendiri. Saya ingin memberi komentar, tapi ternyata terlalu lama untuk itu ...
TL; DR
Pengikatan data dapat menyebabkan masalah kinerja pada halaman yang kompleks.
sumber
Dengan kotor memeriksa
$scope
objekAngular mempertahankan
array
pengamat sederhana di$scope
objek. Jika Anda memeriksa setiap$scope
Anda akan menemukan bahwa itu berisiarray
disebut$$watchers
.Setiap pengamat adalah
object
yang berisi antara lainattribute
nama, atau sesuatu yang lebih rumit.$scope
sebagai kotor.Bagaimana pengamat didefinisikan
Ada banyak cara untuk mendefinisikan pengamat di AngularJS.
Anda secara eksplisit dapat
$watch
sebuahattribute
on$scope
.Anda dapat menempatkan
{{}}
interpolasi di template Anda (pengamat akan dibuat untuk Anda saat ini$scope
).Anda dapat meminta arahan seperti
ng-model
untuk menentukan pengamat untuk Anda.The
$digest
siklus memeriksa semua pengamat terhadap nilai terakhir merekaKetika 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
, memicuAJAX
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 kotorJika 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 lagiKami 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:
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 besarJSON
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:
atau
Ikatan hanya akan dipicu ketika template yang berisi diberikan dan data dimasukkan
$scope
.Ini sangat penting ketika Anda memiliki
ng-repeat
banyak item.sumber
Ini adalah pemahaman dasar saya. Mungkin salah!
$watch
metode.$apply
metode ini.$apply
yang$digest
metode dipanggil yang berjalan melalui masing-masing jam tangan dan memeriksa untuk melihat apakah mereka berubah sejak terakhir kali$digest
berlari.Dalam perkembangan normal, sintaks pengikatan data dalam HTML memberi tahu kompiler AngularJS untuk membuat jam tangan untuk Anda dan metode pengontrol sudah dijalankan di dalam
$apply
. Jadi untuk pengembang aplikasi semuanya transparan.sumber
Saya bertanya-tanya sendiri untuk sementara waktu. Tanpa setters bagaimana
AngularJS
pemberitahuan berubah pada$scope
objek? Apakah itu polling mereka?Apa yang sebenarnya dilakukannya adalah ini: Setiap tempat "normal" yang Anda modifikasi model sudah dipanggil dari nyali
AngularJS
, sehingga secara otomatis memanggil$apply
Anda setelah kode Anda berjalan. Katakanlah controller Anda memiliki metode yang terhubungng-click
pada beberapa elemen. KarenaAngularJS
kabel memanggil metode itu bersama untuk Anda, ia memiliki kesempatan untuk melakukan$apply
di tempat yang tepat. Demikian juga, untuk ekspresi yang muncul tepat di tampilan, mereka dieksekusi olehAngularJS
begitu itu$apply
.Ketika dokumentasi berbicara tentang keharusan memanggil
$apply
secara manual untuk kode di luarAngularJS
, itu berbicara tentang kode yang, ketika dijalankan, tidak berasal dariAngularJS
dirinya sendiri dalam tumpukan panggilan.sumber
Menjelaskan dengan Gambar:
Pengikatan data membutuhkan pemetaan
Referensi dalam ruang lingkup bukanlah referensi dalam template. Saat Anda mengikat data dua objek, Anda membutuhkan objek ketiga yang mendengarkan objek pertama dan memodifikasi objek lainnya.
Di sini, ketika Anda memodifikasi
<input>
, Anda menyentuh data-ref3 . Dan mekanisme klasik data-bind akan mengubah data-ref4 . Jadi bagaimana{{data}}
ekspresi lainnya akan bergerak?Acara mengarah ke $ digest ()
Angular mempertahankan
oldValue
dannewValue
setiap ikatan. Dan setelah setiap acara Angular ,$digest()
loop terkenal akan memeriksa WatchList untuk melihat apakah ada yang berubah. Ini acara Sudut adalahng-click
,ng-change
,$http
selesai ... The$digest()
akan loop selama setiapoldValue
berbeda darinewValue
.Pada gambar sebelumnya, ia akan melihat bahwa data-ref1 dan data-ref2 telah berubah.
Kesimpulan
Ini sedikit seperti Telur dan Ayam. Anda tidak pernah tahu siapa yang memulai, tetapi mudah-mudahan ini berfungsi sebagian besar waktu seperti yang diharapkan.
Poin lainnya adalah Anda dapat dengan mudah memahami dampak mendalam dari pengikatan sederhana pada memori dan CPU. Semoga Desktop cukup gemuk untuk menangani ini. Ponsel tidak sekuat itu.
sumber
Jelas tidak ada pemeriksaan berkala
Scope
apakah ada perubahan pada Objek yang dilampirkan padanya. Tidak semua objek yang dilampirkan pada ruang lingkup ditonton. Cakupan menjaga prototipe $$ pengamat .Scope
hanya beralih melalui ini$$watchers
ketika$digest
dipanggil.Angular menambahkan pengamat ke $$ pengamat untuk masing-masing
$ watch function mengambil tiga parameter:
Ada hal yang menarik dalam Angular yang disebut Digest Cycle. Siklus $ digest dimulai sebagai hasil dari panggilan ke $ scope. $ Digest (). Asumsikan bahwa Anda mengubah model $ scope dalam fungsi handler melalui arahan ng-klik. Jika demikian, AngularJS secara otomatis memicu siklus $ digest dengan memanggil $ digest (). Selain ng-klik, ada beberapa arahan / layanan built-in lain yang memungkinkan Anda mengubah model (mis. Ng-model, $ timeout, dll) dan secara otomatis memicu siklus $ digest. Implementasi kasar dari $ digest terlihat seperti ini.
Jika kami menggunakan fungsi setTimeout () JavaScript untuk memperbarui model ruang lingkup, Angular tidak memiliki cara untuk mengetahui apa yang mungkin Anda ubah. Dalam hal ini adalah tanggung jawab kami untuk memanggil $ apply () secara manual, yang memicu siklus $ digest. Demikian pula, jika Anda memiliki arahan yang mengatur pendengar acara DOM dan mengubah beberapa model di dalam fungsi handler, Anda perlu memanggil $ apply () untuk memastikan perubahan itu berlaku. Gagasan besar dari $ apply adalah bahwa kita dapat mengeksekusi beberapa kode yang tidak menyadari Angular, kode itu mungkin masih mengubah hal-hal pada ruang lingkup. Jika kita membungkus kode itu dalam $ apply, itu akan menangani panggilan $ digest (). Implementasi kasar dari $ apply ().
sumber
AngularJS menangani mekanisme pengikatan data dengan bantuan tiga fungsi hebat: $ watch () , $ digest () dan $ apply () . Sebagian besar waktu AngularJS akan memanggil $ scope. $ Watch () dan $ scope. $ Digest (), tetapi dalam beberapa kasus Anda mungkin harus memanggil fungsi-fungsi ini secara manual untuk memperbarui dengan nilai-nilai baru.
$ tonton () : -
$ digest () -
$ apply () -
sumber
Kebetulan saya perlu menautkan model data seseorang dengan formulir, yang saya lakukan adalah pemetaan langsung data dengan formulir.
Misalnya jika modelnya memiliki sesuatu seperti:
Input kontrol dari formulir:
Dengan begitu jika Anda memodifikasi nilai pengontrol objek, ini akan tercermin secara otomatis dalam tampilan.
Contoh di mana saya lulus model diperbarui dari data server adalah ketika Anda meminta kode pos dan kode pos berdasarkan pada beban tertulis daftar koloni dan kota yang terkait dengan tampilan itu, dan secara default menetapkan nilai pertama dengan pengguna. Dan ini saya bekerja dengan sangat baik, apa yang terjadi, adalah bahwa
angularJS
kadang - kadang membutuhkan beberapa detik untuk menyegarkan model, untuk melakukan ini Anda dapat meletakkan pemintal saat menampilkan data.sumber
Pengikatan data satu arah adalah suatu pendekatan di mana nilai diambil dari model data dan dimasukkan ke dalam elemen HTML. Tidak ada cara untuk memperbarui model dari tampilan. Ini digunakan dalam sistem template klasik. Sistem ini mengikat data hanya dalam satu arah.
Pengikatan data di aplikasi Angular adalah sinkronisasi data secara otomatis antara model dan komponen tampilan.
Pengikatan data memungkinkan Anda memperlakukan model sebagai satu-satunya sumber kebenaran dalam aplikasi Anda. Tampilan adalah proyeksi model setiap saat. Jika model diubah, tampilan mencerminkan perubahan dan sebaliknya.
sumber
Berikut adalah contoh pengikatan data dengan AngularJS, menggunakan bidang input. Saya akan jelaskan nanti
Kode HTML
Kode AngularJS
Seperti yang Anda lihat dalam contoh di atas, AngularJS menggunakan
ng-model
untuk mendengarkan dan menonton apa yang terjadi pada elemen HTML, terutama diinput
bidang. Ketika sesuatu terjadi, lakukan sesuatu. Dalam kasus kami,ng-model
terikat dengan pandangan kami, menggunakan notasi kumis{{}}
. Apa pun yang diketik di dalam bidang input ditampilkan di layar secara instan. Dan itulah keindahan dari pengikatan data, menggunakan AngularJS dalam bentuknya yang paling sederhana.Semoga ini membantu.
Lihat contoh yang berfungsi di sini di Codepen
sumber
AngularJs mendukung pengikatan data dua arah .
Berarti Anda dapat mengakses data View -> Controller & Controller -> View
Untuk Kel.
1)
O / P
Anda dapat mengikat data dalam
ng-model
Suka: -2)
Di sini, dalam contoh di atas, apa pun yang akan diberikan oleh pengguna, Itu akan terlihat dalam
<div>
tag.Jika ingin mengikat input dari html ke controller: -
3)
Di sini jika Anda ingin menggunakan input
name
pada controller,ng-model
mengikat pandangan kita dan membuatnya dalam ekspresi{{ }}
.ng-model
adalah data yang ditampilkan kepada pengguna dalam tampilan dan yang berinteraksi dengan pengguna.Sehingga mudah untuk mengikat data di AngularJs.
sumber
Angular.js membuat pengamat untuk setiap model yang kami buat dalam tampilan. Setiap kali model diubah, kelas "ng-dirty" ditambahkan ke model, sehingga pengamat akan mengamati semua model yang memiliki kelas "ng-dirty" & memperbarui nilainya dalam controller & sebaliknya.
sumber
pengikatan data:
Apa yang mengikat data?
Setiap kali pengguna mengubah data dalam tampilan, terjadi pembaruan dari perubahan dalam model lingkup, dan sebaliknya.
Bagaimana itu mungkin?
Jawaban singkat: Dengan bantuan siklus cerna.
Deskripsi: Angular js mengatur pengamat pada model ruang lingkup, yang mengaktifkan fungsi pendengar jika ada perubahan dalam model.
// Kode pembaruan Dom dengan nilai baru
});
Jadi Kapan dan Bagaimana fungsi pengamat dipanggil?
Fungsi pengamat disebut sebagai bagian dari siklus digest.
Siklus pencernaan disebut dipicu secara otomatis sebagai bagian dari sudut js yang dibangun dalam arahan / layanan seperti ng-model, ng-bind, $ timeout, ng-klik dan lain-lain .. yang memungkinkan Anda memicu siklus intisari.
Fungsi siklus pencernaan:
yaitu
$rootScope.$apply()
Catatan: $ apply () sama dengan $ rootScope. $ Digest () ini berarti pemeriksaan kotor dimulai langsung dari root atau atas atau ruang lingkup orang tua ke semua cakupan $ child dalam aplikasi js angular.
Fitur di atas berfungsi di browser IE untuk versi yang disebutkan juga hanya dengan memastikan aplikasi Anda adalah aplikasi js angular yang berarti Anda menggunakan file skrip kerangka kerja angular yang dirujuk dalam tag skrip.
Terima kasih.
sumber