Pertanyaan Bagaimana cara menggunakan $ scope. $ Watch dan $ scope. $ Apply di AngularJS?


Saya tidak mengerti cara menggunakannya $scope.$watch dan $scope.$apply. Dokumentasi resmi tidak membantu.

Yang tidak saya pahami secara spesifik:

  • Apakah mereka terhubung ke DOM?
  • Bagaimana cara saya memperbarui perubahan DOM ke model?
  • Apa titik koneksi di antara mereka?

Saya mencoba tutorial ini, tetapi butuh pemahaman $watch dan $apply begitu saja.

Apa yang $apply dan $watch lakukan, dan bagaimana cara menggunakannya dengan tepat?


1007
2018-02-27 12:50


asal


Jawaban:


Anda perlu menyadari tentang bagaimana AngularJS bekerja untuk memahaminya.

Siklus mencerna dan $ cakupan

Pertama dan terutama, AngularJS mendefinisikan konsep yang disebut siklus cerna. Siklus ini dapat dianggap sebagai loop, selama AngularJS memeriksa apakah ada perubahan pada semua variabel diawasi oleh semua $scopes. Jadi, jika Anda punya $scope.myVar didefinisikan dalam pengontrol Anda dan variabel ini adalah ditandai untuk diawasi, maka Anda secara implisit memberitahu AngularJS untuk memantau perubahan myVar di setiap iterasi loop.

Pertanyaan lanjutan yang wajar adalah: Apakah semuanya terkait $scope diawasi? Untungnya, tidak. Jika Anda akan memperhatikan perubahan pada setiap objek di Anda $scope, maka dengan cepat lingkaran intaian akan memakan waktu lama untuk mengevaluasi dan Anda akan segera mengalami masalah kinerja. Itulah sebabnya tim AngularJS memberi kami dua cara untuk menyatakan beberapa $scope variabel saat ditonton (baca di bawah).

$ arloji membantu untuk mendengarkan perubahan ruang lingkup

Ada dua cara untuk menyatakan a $scope variabel saat ditonton.

  1. Dengan menggunakannya di template Anda melalui ekspresi <span>{{myVar}}</span>
  2. Dengan menambahkannya secara manual melalui $watch layanan

Ad 1) Ini adalah skenario yang paling umum dan saya yakin Anda pernah melihatnya sebelumnya, tetapi Anda tidak tahu bahwa ini telah membuat jam di latar belakang. Ya, benar! Menggunakan arahan AngularJS (seperti ng-repeat) juga dapat membuat jam tangan implisit.

Iklan 2) Ini adalah cara Anda membuat milik Anda sendiri jam tangan. $watch layanan membantu Anda menjalankan beberapa kode ketika beberapa nilai melekat pada $scope telah berubah. Ini jarang digunakan, tetapi terkadang sangat membantu. Misalnya, jika Anda ingin menjalankan beberapa kode setiap kali perubahan 'myVar', Anda dapat melakukan hal berikut:

function MyController($scope) {

    $scope.myVar = 1;

    $scope.$watch('myVar', function() {
        alert('hey, myVar has changed!');
    });

    $scope.buttonClicked = function() {
        $scope.myVar = 2; // This will trigger $watch expression to kick in
    };
}

$ apply memungkinkan untuk mengintegrasikan perubahan dengan siklus intisari

Anda bisa memikirkan itu $apply berfungsi sebagai mekanisme integrasi. Anda lihat, setiap kali Anda mengubah beberapa variabel yang diawasi yang melekat pada $scope objek langsung, AngularJS akan tahu bahwa perubahan telah terjadi. Ini karena AngularJS sudah tahu untuk memantau perubahan itu. Jadi jika itu terjadi dalam kode yang dikelola oleh kerangka kerja, siklus intisari akan berjalan.

Namun, terkadang Anda mau mengubah beberapa nilai di luar dunia AngularJS dan lihat perubahan menyebar secara normal. Pertimbangkan ini - Anda punya $scope.myVar nilai yang akan dimodifikasi dalam jQuery $.ajax()pawang Ini akan terjadi di beberapa titik di masa depan. AngularJS tidak sabar menunggu ini terjadi, karena belum diinstruksikan untuk menunggu jQuery.

Untuk mengatasi ini, $apply telah diperkenalkan. Ini memungkinkan Anda memulai siklus pencernaan secara eksplisit. Namun, Anda sebaiknya hanya menggunakan ini untuk memigrasikan beberapa data ke AngularJS (integrasi dengan kerangka lain), tetapi jangan pernah menggunakan metode ini dikombinasikan dengan kode AngularJS reguler, karena AngularJS akan melemparkan kesalahan itu.

Bagaimana semua ini terkait dengan DOM?

Nah, Anda harus benar-benar mengikuti tutorial lagi, sekarang setelah Anda mengetahui semua ini. Siklus intisari akan memastikan bahwa UI dan kode JavaScript tetap tersinkronisasi, dengan mengevaluasi setiap pengamat yang melekat pada semua $scopes selama tidak ada perubahan. Jika tidak ada lagi perubahan yang terjadi di loop digest, maka dianggap selesai.

Anda dapat melampirkan objek ke $scope objek baik secara eksplisit di Controller, atau dengan mendeklarasikannya {{expression}} terbentuk langsung di tampilan.

Saya harap itu membantu menjelaskan beberapa pengetahuan dasar tentang semua ini.

Bacaan lebih lanjut:


1648
2018-02-27 13:14



Di AngularJS, kami memperbarui model kami, dan pandangan / template kami memperbarui DOM "secara otomatis" (melalui arahan bawaan atau kustom).

$ apply dan $ watch, keduanya merupakan metode Scope, tidak terkait dengan DOM.

Itu Konsep halaman (bagian "Runtime") memiliki penjelasan yang cukup bagus dari $ digest loop, $ apply, $ evalAsync queue dan daftar $ watch. Inilah gambar yang menyertai teks:

$digest loop

Kode apa pun yang memiliki akses ke ruang lingkup - biasanya pengendali dan arahan (fungsi tautan dan / atau pengontrolnya) - dapat menyiapkan "watchExpression"AngularJS akan mengevaluasi terhadap ruang lingkup itu. Evaluasi ini terjadi setiap kali AngularJS memasukkan $ digest loop-nya (khususnya, loop" daftar pantauan "). Anda dapat menonton properti lingkup individual, Anda dapat mendefinisikan fungsi untuk menonton dua properti bersama-sama, Anda dapat melihat lamanya array, dll.

Ketika hal-hal terjadi "di dalam AngularJS" - misalnya, Anda mengetikkan ke dalam kotak teks yang memiliki penyatuan dua arah dua arah AngularJS (yaitu, menggunakan model-ng), callback $ http callback, dll - $ berlaku telah dipanggil, jadi kami berada di dalam persegi panjang "AngularJS" pada gambar di atas. Semua watchExpressions akan dievaluasi (mungkin lebih dari satu kali - hingga tidak ada perubahan lebih lanjut terdeteksi).

Ketika sesuatu terjadi "di luar AngularJS" - misalnya, Anda menggunakan bind () dalam arahan dan kemudian peristiwa itu diaktifkan, sehingga panggilan balik Anda dipanggil, atau beberapa callback call jQuery yang terdaftar - kami masih berada di kotak "Asli". Jika kode callback memodifikasi apa pun yang setiap jam tangan sedang tonton, panggil $ berlaku untuk masuk ke dalam persegi panjang AngularJS, menyebabkan loop $ digest dijalankan, dan karenanya AngularJS akan melihat perubahan dan melakukan sihirnya.


152
2018-02-28 00:48



Blog ini telah mencakup semua yang membuat contoh dan penjelasan yang bisa dimengerti.

The AngularJS $scope fungsi $watch(), $digest() dan $apply() adalah beberapa fungsi sentral di AngularJS. Memahami $watch(), $digest() dan $apply() sangat penting untuk memahami AngularJS.

Ketika Anda membuat data yang mengikat dari suatu tempat dalam pandangan Anda ke variabel pada objek lingkup $, AngularJS membuat "jam tangan" secara internal. Jam tangan berarti AngularJS melihat perubahan dalam variabel pada $scope object. Kerangka kerjanya adalah "mengawasi" variabel. Jam tangan dibuat menggunakan $scope.$watch() fungsi yang akan saya bahas nanti dalam teks ini.

Pada poin-poin penting dalam aplikasi Anda, AngularJS memanggil $scope.$digest() fungsi. Fungsi ini beriterasi melalui semua jam dan memeriksa apakah ada variabel yang diawasi telah berubah. Jika variabel yang diawasi telah berubah, fungsi pendengar yang sesuai dipanggil. Fungsi pendengar melakukan pekerjaan apa pun yang perlu dilakukan, misalnya mengubah teks HTML untuk mencerminkan nilai baru dari variabel yang diawasi. Jadi, itu $digest() fungsi inilah yang memicu pengikatan data untuk memperbarui.

Sebagian besar waktu AngularJS akan memanggil $ scope. $ Watch () dan $scope.$digest() berfungsi untuk Anda, tetapi dalam beberapa situasi Anda mungkin harus memanggil mereka sendiri. Oleh karena itu sangat bagus untuk mengetahui cara kerjanya.

Itu $scope.$apply() fungsi digunakan untuk menjalankan beberapa kode, dan kemudian memanggil $scope.$digest() setelah itu, semua jam diperiksa dan fungsi pendengar jam yang sesuai dipanggil. Itu $apply() fungsi berguna ketika mengintegrasikan AngularJS dengan kode lain.

Saya akan membahas lebih detail tentang $watch(), $digest() dan $apply() berfungsi di sisa teks ini.

$ jam ()

Itu $scope.watch() fungsi menciptakan pengawasan beberapa variabel. Saat Anda mendaftarkan jam, Anda melewatkan dua fungsi sebagai parameter ke $watch() fungsi:

  • Fungsi nilai
  • Fungsi pendengar

Berikut ini contohnya:

$scope.$watch(function() {},
              function() {}
             );

Fungsi pertama adalah fungsi nilai dan fungsi kedua adalah fungsi pendengar.

Fungsi nilai harus mengembalikan nilai yang sedang ditonton. AngularJS kemudian dapat memeriksa nilai yang dikembalikan terhadap nilai fungsi jam yang dikembalikan terakhir kali. Dengan cara itu AngularJS dapat menentukan apakah nilai telah berubah. Berikut ini contohnya:

$scope.$watch(function(scope) { return scope.data.myVar },
              function() {}
             );

Fungsi contoh valule ini mengembalikan $scope variabel scope.data.myVar. Jika nilai variabel ini berubah, nilai yang berbeda akan dikembalikan, dan AngularJS akan memanggil fungsi pendengar.

Perhatikan bagaimana fungsi nilai mengambil ruang lingkup sebagai parameter (tanpa $ dalam nama). Melalui parameter ini fungsi nilai dapat mengakses $scope dan variabelnya. Fungsi nilai juga dapat menonton variabel global jika Anda membutuhkannya, tetapi paling sering Anda akan menonton $scope variabel.

Fungsi pendengar harus melakukan apa pun yang perlu dilakukan jika nilai telah berubah. Mungkin Anda perlu mengubah konten dari variabel lain, atau mengatur konten elemen HTML atau sesuatu. Berikut ini contohnya:

$scope.$watch(function(scope) { return scope.data.myVar },
              function(newValue, oldValue) {
                  document.getElementById("").innerHTML =
                      "" + newValue + "";
              }
             );

Contoh ini menetapkan HTML bagian dalam dari elemen HTML ke nilai baru dari variabel, yang disematkan dalam elemen b yang membuat nilai menjadi tebal. Tentu saja Anda bisa melakukan ini menggunakan kode {{ data.myVar }, tetapi ini hanyalah contoh dari apa yang dapat Anda lakukan di dalam fungsi pendengar.

$ digest ()

Itu $scope.$digest() fungsi iterates melalui semua jam di $scope object, dan anak-anak $ objek lingkup (jika memiliki). Kapan $digest() iterasi atas jam tangan, itu memanggil fungsi nilai untuk setiap jam. Jika nilai yang dikembalikan oleh fungsi nilai berbeda dari nilai yang dikembalikan terakhir kali dipanggil, maka fungsi pendengar untuk jam itu dipanggil.

Itu $digest() fungsi ini disebut setiap kali AngularJS berpikir itu perlu. Misalnya, setelah penangan tombol klik telah dijalankan, atau setelah AJAX panggil kembali (setelah fungsi callback selesai () / gagal () telah dijalankan).

Anda mungkin mengalami beberapa kasus pojok di mana AngularJS tidak memanggil $digest() berfungsi untuk Anda. Anda biasanya akan mendeteksi bahwa dengan memperhatikan bahwa binding data tidak memperbarui nilai yang ditampilkan. Dalam hal ini, hubungi $scope.$digest() dan seharusnya berhasil. Atau, Anda mungkin bisa menggunakannya $scope.$apply() sebaliknya yang akan saya jelaskan di bagian selanjutnya.

$ apply ()

Itu $scope.$apply() function mengambil fungsi sebagai parameter yang dieksekusi, dan setelah itu $scope.$digest() disebut secara internal. Hal itu mempermudah Anda untuk memastikan bahwa semua jam diperiksa, dan dengan demikian semua jilid data disegarkan. Ini adalah sebuah $apply() contoh:

$scope.$apply(function() {
    $scope.data.myVar = "Another value";
});

Fungsi diteruskan ke $apply() berfungsi sebagai parameter akan mengubah nilai $scope.data.myVar. Ketika fungsi keluar AngularJS akan memanggil $scope.$digest() berfungsi sehingga semua jam diperiksa untuk perubahan dalam nilai yang diawasi.

Contoh

Untuk mengilustrasikan caranya $watch(), $digest() dan $apply() bekerja, lihat contoh ini:

<div ng-controller="myController">
    {{data.time}}

    <br/>
    <button ng-click="updateTime()">update time - ng-click</button>
    <button id="updateTimeButton"  >update time</button>
</div>


<script>
    var module       = angular.module("myapp", []);
    var myController1 = module.controller("myController", function($scope) {

        $scope.data = { time : new Date() };

        $scope.updateTime = function() {
            $scope.data.time = new Date();
        }

        document.getElementById("updateTimeButton")
                .addEventListener('click', function() {
            console.log("update time clicked");
            $scope.data.time = new Date();
        });
    });
</script>

teladannya mengikat $scope.data.time variabel ke instruksi interpolasi yang menggabungkan nilai variabel ke dalam halaman HTML. Pengikatan ini menciptakan jam tangan secara internal pada $scope.data.time variable.

Contoh ini juga mengandung dua tombol. Tombol pertama memiliki ng-click pendengar yang melekat padanya. Ketika tombol itu diklik $scope.updateTime() fungsi dipanggil, dan setelah itu AngularJS memanggil $scope.$digest() sehingga data bindings diperbarui.

Tombol kedua mendapat pendengar peristiwa JavaScript standar yang melekat padanya dari dalam fungsi pengontrol. Ketika tombol kedua diklik, fungsi pendengar dieksekusi. Seperti yang Anda lihat, fungsi pendengar untuk kedua tombol hampir sama, tetapi ketika fungsi pendengar tombol kedua dipanggil, pengikatan data tidak diperbarui. Itu karena $scope.$digest() tidak dipanggil setelah pendengar acara tombol kedua dijalankan. Jadi, jika Anda mengklik tombol kedua waktu diperbarui di $scope.data.time variabel, tetapi waktu baru tidak pernah ditampilkan.

Untuk memperbaikinya kita bisa menambahkan $scope.$digest() panggilan ke baris terakhir dari pendengar acara tombol, seperti ini:

document.getElementById("updateTimeButton")
        .addEventListener('click', function() {
    console.log("update time clicked");
    $scope.data.time = new Date();
    $scope.$digest();
});

Daripada menelepon $digest() di dalam fungsi pendengar tombol Anda juga bisa menggunakan $apply() berfungsi seperti ini:

document.getElementById("updateTimeButton")
        .addEventListener('click', function() {
    $scope.$apply(function() {
        console.log("update time clicked");
        $scope.data.time = new Date();
    });
});

Perhatikan bagaimana $scope.$apply() fungsi dipanggil dari dalam pendengar acara tombol, dan bagaimana pembaruan $scope.data.timevariabel dilakukan di dalam fungsi yang dilewatkan sebagai parameter ke $apply() fungsi. Ketika $apply() panggilan fungsi selesai panggilan AngularJS $digest() secara internal, jadi semua binding data diperbarui.


53
2018-02-22 10:13



AngularJS memperluas ini loop kejadian, menciptakan sesuatu yang disebut AngularJS context.

$ jam ()

Setiap kali Anda mengikat sesuatu di UI, Anda memasukkan a $watch di sebuah $watch daftar.

User: <input type="text" ng-model="user" />
Password: <input type="password" ng-model="pass" />

Di sini kita punya $scope.user, yang terikat pada input pertama, dan kami punya $scope.pass, yang terikat ke yang kedua. Melakukan ini kita tambahkan dua $watchsampai ke $watch daftar.

Ketika kami template dimuat, AKA dalam fase penautan, kompiler akan mencari setiap direktif dan membuat semua $watches yang dibutuhkan.

AngularJS menyediakan $watch, $watchcollection dan $watch(true). Di bawah ini adalah diagram rapi yang menjelaskan semua tiga yang diambil pengamat secara mendalam.

Enter image description here

angular.module('MY_APP', []).controller('MyCtrl', MyCtrl)
function MyCtrl($scope,$timeout) {
  $scope.users = [{"name": "vinoth"},{"name":"yusuf"},{"name":"rajini"}];

  $scope.$watch("users", function() {
    console.log("**** reference checkers $watch ****")
  });

  $scope.$watchCollection("users", function() {
    console.log("**** Collection  checkers $watchCollection ****")
  });

  $scope.$watch("users", function() {
    console.log("**** equality checkers with $watch(true) ****")
  }, true);

  $timeout(function(){
     console.log("Triggers All ")
     $scope.users = [];
     $scope.$digest();

     console.log("Triggers $watchCollection and $watch(true)")
     $scope.users.push({ name: 'Thalaivar'});
     $scope.$digest();

     console.log("Triggers $watch(true)")
     $scope.users[0].name = 'Superstar';
     $scope.$digest();
  });
}

http://jsfiddle.net/2Lyn0Lkb/

$digest lingkaran

Ketika browser menerima acara yang dapat dikelola oleh konteks AngularJS $digest loop akan dipecat. Lingkaran ini dibuat dari dua loop yang lebih kecil. Satu proses $evalAsync antrian, dan yang lainnya memproses $watch list. Itu $digest akan melewati daftar $watch yang kita miliki

app.controller('MainCtrl', function() {
  $scope.name = "vinoth";

  $scope.changeFoo = function() {
      $scope.name = "Thalaivar";
  }
});

{{ name }}
<button ng-click="changeFoo()">Change the name</button>

Di sini kita hanya punya satu $watch karena ng-klik tidak membuat jam tangan apa pun.

Kami menekan tombol.

  1. Peramban menerima acara yang akan memasuki konteks AngularJS
  2. Itu $digest loop akan berjalan dan akan meminta setiap $ watch untuk perubahan.
  3. Sejak itu $watch yang sedang mengamati perubahan dalam scope.name melaporkan perubahan, itu akan memaksa yang lain $digest lingkaran.
  4. Lingkaran baru tidak melaporkan apa pun.
  5. Peramban mendapatkan kontrol kembali dan itu akan memperbarui DOM mencerminkan nilai baru dari $ scope.name
  6. Yang penting di sini adalah bahwa SETIAP peristiwa yang memasuki konteks AngularJS akan menjalankan a $digest lingkaran. Itu berarti bahwa setiap kali kita menulis surat dalam sebuah masukan, perulangan akan menjalankan pemeriksaan setiap $watch di halaman ini.

$ apply ()

Jika Anda menelepon $apply ketika suatu peristiwa dipecat, itu akan melalui konteks bersiku-siku, tetapi jika Anda tidak menyebutnya, ia akan berjalan di luarnya. Itu semudah itu. $apply akan memanggil $digest() loop secara internal dan akan berulang pada semua jam untuk memastikan DOM diperbarui dengan nilai yang baru diperbarui.

Itu $apply() metode akan memicu pengamat di seluruh $scope rantai sedangkan $digest() metode hanya akan memicu pengamat pada saat ini $scope dan itu children. Ketika tidak ada yang lebih tinggi $scope objek perlu mengetahui tentang perubahan lokal, yang dapat Anda gunakan $digest().


37
2018-04-22 13:06



Ada $watchGroup dan $watchCollection demikian juga. Secara khusus, $watchGroup sangat membantu jika Anda ingin memanggil fungsi untuk memperbarui objek yang memiliki beberapa properti dalam tampilan yang bukan objek dom, misalnya. tampilan lain dalam kanvas, webGL, atau permintaan server. Di sini, dokumentasi link.


17
2018-03-18 10:50



Saya menemukan video yang sangat mendalam yang meliputi $watch, $apply, $digest dan mencerna siklus di:

Berikut ini adalah beberapa slide yang digunakan dalam video-video tersebut untuk menjelaskan konsepnya (berjaga-jaga, jika tautan di atas dihapus / tidak berfungsi).

Enter image description here

Pada gambar di atas, "$ scope.c" tidak diawasi karena tidak digunakan dalam salah satu binding data (dalam markup). Dua yang lainnya ($scope.a dan $scope.b) akan ditonton.

Enter image description here

Dari gambar di atas: Berdasarkan peristiwa browser masing-masing, AngularJS menangkap peristiwa tersebut, melakukan siklus intisari (melalui semua jam untuk perubahan), menjalankan fungsi jam dan memperbarui DOM. Jika tidak ada acara browser, siklus intisari dapat dipicu secara manual $apply atau $digest.

Lebih tentang $apply dan $digest:

Enter image description here


15
2017-11-20 16:28



Baru selesai membaca SEMUA di atas, membosankan dan mengantuk (maaf tapi benar). Sangat teknis, mendalam, detail, dan kering. Mengapa saya menulis? Karena AngularJS sangat besar, banyak konsep yang saling terhubung dapat mengubah siapa pun menjadi gila. Saya sering bertanya pada diri sendiri, apakah saya tidak cukup pandai untuk memahaminya? Tidak! Itu karena begitu sedikit yang bisa menjelaskan teknologi dalam bahasa untuk-dummie tanpa semua istilah! Oke, coba saya coba:

1) Mereka semua adalah hal yang didorong oleh peristiwa. (Saya mendengar tawa, tetapi baca terus)

Jika Anda tidak tahu apa yang digerakkan oleh kejadian adalah Kemudian   pikir Anda menempatkan sebuah tombol   di halaman, hook it up w / fungsi menggunakan "on-klik", menunggu   pengguna untuk mengkliknya untuk memicu tindakan yang Anda tanam di dalam   fungsi. Atau pikirkan "pemicu" dari SQL Server / Oracle.

2) Jam tangan $ adalah "di-klik". 

Apa yang khusus tentang itu dibutuhkan 2 fungsi sebagai parameter, yang pertama   memberikan nilai dari peristiwa, yang kedua membawa nilai ke dalamnya   pertimbangan...

3) $ digest adalah bos yang memeriksa tanpa lelah, bla-bla-bla tapi bos yang baik.

4) $ apply memberi Anda cara ketika Anda ingin melakukannya secara manual, seperti gagal-bukti (jika saat-saat tidak menendang masuk, Anda memaksanya untuk lari.)

Sekarang, buatlah menjadi visual. Bayangkan ini untuk membuatnya lebih mudah untuk mendapatkan ide:

Di dalam restoran, 

- TUNGGU seharusnya menerima pesanan dari pelanggan, ini

$watch(
  function(){return orders;},
  function(){Kitchen make it;}
);

- MANAJER berlarian untuk memastikan semua pelayan terjaga, responsif terhadap tanda perubahan apa pun dari pelanggan. Ini adalah $digest()

- PEMILIK memiliki kekuatan tertinggi untuk mendorong semua orang atas permintaan, ini $apply()


10
2018-02-07 01:20