AngularJS: Perbedaan antara metode $ observ dan $ watch


378

Saya tahu bahwa keduanya Watchersdan Observersdihitung segera setelah sesuatu dalam $scopeperubahan di AngularJS. Tapi tidak bisa mengerti apa sebenarnya perbedaan antara keduanya.

Pemahaman awal saya adalah yang Observersdihitung untuk ekspresi sudut yang merupakan kondisi di sisi HTML tempat Watchersdieksekusi ketika $scope.$watch()fungsi dieksekusi. Apakah saya berpikir dengan benar?


1
Hasil edit Anda tidak membantu dan agak memusuhi. Harap perhatikan orang lain yang datang ke sini untuk bantuan aktual.
— smalone

@smalone berubah. Terima kasih dan maaf!
— Abilash

👍 Jangan khawatir. Terima kasih telah memperbaikinya.
— smalone

Jawaban:


608

$ observ () adalah metode padaobjek Attributes , dan karenanya, hanya dapat digunakan untuk mengamati / menonton perubahan nilai atribut DOM. Ini hanya digunakan / disebut arahan dalam. Gunakan $ mengamati ketika Anda perlu mengamati / menonton atribut DOM yang berisi interpolasi (yaitu, {{}} 's).
Misalnya,attr1="Name: {{name}}"maka dalam Instruksi:attrs.$observe('attr1', ...).
(Jika Anda mencobanyascope.$watch(attrs.attr1, ...)tidak akan berhasil karena {{}} s - Anda akan mendapatkannyaundefined.) Gunakan $ watch untuk yang lainnya.

$ watch () lebih rumit. Ia dapat mengamati / menonton "ekspresi", di mana ekspresi dapat berupa fungsi atau string. Jika ekspresi adalah string, itu adalah $ parse 'd (yaitu, dievaluasi sebagai ekspresi Angular ) ke dalam suatu fungsi. (Fungsi inilah yang disebut setiap siklus intisari.) Ekspresi string tidak dapat berisi {{}}. $ watch adalah metode padaobjek Lingkup , sehingga dapat digunakan / dipanggil di mana pun Anda memiliki akses ke objek lingkup, maka dalam

  • controller - controller apa saja - yang dibuat melalui ng-view, ng-controller, atau directive controller
  • fungsi penautan dalam arahan, karena ini juga memiliki akses ke ruang lingkup

Karena string dievaluasi sebagai ekspresi Angular, $ watch sering digunakan ketika Anda ingin mengamati / menonton properti model / lingkup. Misalnya,, attr1="myModel.some_prop"lalu dalam fungsi pengontrol atau tautan: scope.$watch('myModel.some_prop', ...)atau scope.$watch(attrs.attr1, ...)(atau scope.$watch(attrs['attr1'], ...)).
(Jika Anda mencoba, attrs.$observe('attr1')Anda akan mendapatkan string myModel.some_prop, yang mungkin bukan yang Anda inginkan.)

Seperti dibahas dalam komentar pada jawaban @ PrimosK, semua $ mengamati dan $ jam diperiksa setiap siklus intisari .

Arahan dengan lingkup isolasi lebih rumit. Jika sintaks '@' digunakan, Anda dapat $ mengamati atau $ menonton atribut DOM yang berisi interpolasi (yaitu, {{}}). (Alasan kerjanya dengan $ watch adalah karena sintaks '@' melakukan interpolasi untuk kita, maka $ watch melihat string tanpa {{}} 's.) Untuk membuatnya lebih mudah untuk mengingat yang harus digunakan saat, saya sarankan menggunakan $ perhatikan untuk kasus ini juga.

Untuk membantu menguji semua ini, saya menulis sebuah Plunker yang mendefinisikan dua arahan. Satu ( d1) tidak membuat ruang lingkup baru, yang lain ( d2) menciptakan ruang lingkup terisolasi. Setiap arahan memiliki enam atribut yang sama. Setiap atribut adalah $ observ'd dan $ watch'ed.

<div d1 attr1="{{prop1}}-test" attr2="prop2" attr3="33" attr4="'a_string'"
        attr5="a_string" attr6="{{1+aNumber}}"></div>

Lihatlah log konsol untuk melihat perbedaan antara $ observ dan $ watch dalam fungsi penautan. Kemudian klik tautan dan lihat $ mengamati dan $ jam tangan mana yang dipicu oleh perubahan properti yang dilakukan oleh pengendali klik.

Perhatikan bahwa ketika fungsi tautan berjalan, atribut apa pun yang mengandung {{}} belum dievaluasi (jadi jika Anda mencoba memeriksa atribut, Anda akan mendapatkannya undefined). Satu-satunya cara untuk melihat nilai-nilai yang diinterpolasi adalah dengan menggunakan $ observ (atau $ watch jika menggunakan lingkup isolat dengan '@'). Oleh karena itu, mendapatkan nilai atribut ini adalah operasi yang tidak sinkron . (Dan inilah mengapa kita membutuhkan fungsi $ mengamati dan $ menonton.)

Terkadang Anda tidak perlu $ mengamati atau $ menonton. Misalnya, jika atribut Anda berisi nomor atau boolean (bukan string), hanya mengevaluasi sekali: attr1="22", maka dalam, katakanlah, fungsi menghubungkan Anda: var count = scope.$eval(attrs.attr1). Jika itu hanya string konstan - attr1="my string"- maka gunakan saja attrs.attr1direktif Anda (tidak perlu $ eval ()).

Lihat juga posting grup google Vojta tentang $ watch expressions.


13
Penjelasan hebat! +1
— PrimosK

4
Jawaban bagus! Apakah Anda tahu mengapa ng-src/ng-hrefpenggunaan attr.$observebukan scope.$watchitu?
— okm

4
+1 Untuk Paus AngularJS! Setiap kali saya mencari Stack untuk beberapa info tentang masalah Angular terbaru saya, akhirnya saya membaca @MarkRajcok jawaban yang diterima.
— GFoley83

1
Terima kasih untuk kiriman yang bagus. ruang lingkup. $ eval (item) sangat membantu. Jika item adalah string json, itu dikonversi ke objek json.
— bnguyen82

5
@takakisquare, mereka dapat dipertukarkan saat menggunakan @sintaks. Saya percaya tidak ada perbedaan kinerja (tapi saya belum melihat kode sumber yang sebenarnya).
— Mark Rajcok

25

Jika saya mengerti pertanyaan Anda dengan benar, Anda bertanya apa bedanya jika Anda mendaftar dengan panggilan balik pendengar $watchatau jika Anda melakukannya $observe.

Register callback dengan $watchdipecat ketika $digestdieksekusi.

Callback terdaftar dengan $observedipanggil ketika nilai perubahan atribut yang mengandung interpolasi (misalnya attr="{{notJetInterpolated}}").


Di dalam arahan Anda dapat menggunakan keduanya dengan cara yang sangat mirip:

    attrs.$observe('attrYouWatch', function() {
         // body
    });

atau

    scope.$watch(attrs['attrYouWatch'], function() {
         // body
    });

3
Sebenarnya, karena setiap perubahan tercermin dalam $digestfase, aman untuk mengasumsikan bahwa $observepanggilan balik akan dipanggil $digest. Dan $watchpanggilan balik juga akan dipanggil $digesttetapi kapan pun nilainya berubah. Saya pikir mereka melakukan pekerjaan yang sama persis: "perhatikan ekspresi, panggil panggilan balik nilainya berubah". Perbedaan kata kunci mungkin hanya gula sintaksis karena tidak membingungkan pengembang.
— Umur Kontacı

1
@ fastreload, saya setuju dengan komentar Anda .. Ditulis dengan baik!
— PrimosK

@ fastreload ... Terima kasih atas penjelasannya. Jika saya mengerti dengan benar, Pengamat adalah untuk Ekspresi Angular. Apakah saya benar?
— Abilash

@RimosK: menambahkan Anda untuk komentar saya sebelumnya.
— Abilash

2
Pengamat @Abilash adalah untuk menonton atribut dom, bukan hanya ekspresi. Jadi jika Anda mengubah nilai atribut sendiri, itu akan tercermin dalam siklus intisari berikutnya.
— Umur Kontacı

1

Saya pikir ini cukup jelas:

  • $ mengamati digunakan dalam menghubungkan fungsi arahan.
  • $ watch digunakan pada scope untuk melihat setiap perubahan nilainya.

Perlu diingat : kedua fungsi memiliki dua argumen,

$observe/$watch(value : string, callback : function);
  • value : selalu berupa referensi string ke elemen yang ditonton (nama variabel lingkup atau nama atribut direktif yang akan ditonton)
  • callback : fungsi yang akan dieksekusi dari formulirfunction (oldValue, newValue)

Saya telah membuat plunker, jadi Anda benar-benar bisa memahami pemanfaatan keduanya. Saya telah menggunakan analogi Chameleon untuk membuatnya lebih mudah digambarkan.


2
Cukup jelas tentang penggunaannya. Tapi mengapa pertanyaannya. Markus menyimpulkannya dengan indah.
— Abilash

3
Saya pikir params mungkin diaktifkan - tampaknya melewati newValue, lalu oldValue ke attrs. $ Mengamati (). . .
— blaster

0

Mengapa $ mengamati berbeda dari $ menonton?

WatchExpression dievaluasi dan dibandingkan dengan nilai sebelumnya setiap siklus digest (), jika ada perubahan dalam nilai watchExpression, fungsi jam disebut.

$ observ khusus untuk mengamati nilai yang diinterpolasi. Jika nilai atribut direktif diinterpolasi, misalnya dir-attr="{{ scopeVar }}", fungsi mengamati hanya akan dipanggil ketika nilai interpolasi diatur (dan karena itu ketika $ digest telah menentukan pembaruan harus dilakukan). Pada dasarnya sudah ada pengamat interpolasi, dan fungsi $ mengamati dukung itu.

Lihat $ mengamati & $ set di compile.js

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.