cari
Rumahhujung hadapan webtutorial jsAngularJS双向数据绑定原理(详细教程)

AngularJS双向数据绑定原理(详细教程)

Jun 08, 2018 pm 05:57 PM
$watchangularjs

这篇文章主要介绍了AngularJS双向数据绑定原理之$watch、$apply和$digest的应用,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

引子

这篇文章是写给AngularJS新手的,如果你已经对AngularJS的双向数据绑定有了深入的了解,直接去阅读源代码好了。

背景

AngularJS开发者都想知道双向数据绑定是怎么实现的。与data-binding相关的术语琳琅满目: $watch,$apply,$digest,dirty-checking等等它们是如何工作的呢?让我们从头开始讲起吧

AngularJS 的双向数据绑定是被浏览器逼的

浏览器看上去很美,其实在数据交互这块儿,由于浏览器的“不作为”,导致浏览器的数据刷新成为一个难题。具体来说,浏览器可以很容易地监听一个事件,比如:用户点击一个按钮,或者在输入框里输入东西,为此还提供了事件回调函数的API,事件的回调函数就会在javascript解释器里执行;但反过来就没这么简单了,如果来自后台的数据发生了变化,需要通知给浏览器,让浏览器刷新,浏览器并没有提供这样的数据交互机制,对于开发者来说,这是一个难以逾越的障碍,怎么办呢? AngularJS出现了,它通过$scope 很好地实现了双向数据绑定,其背后的原理就是$watch,$apply,$digest,dirty-checking

$watch 队列($watch list)

从字面上看,watch 是观察的意思。 每次绑定一些东西到浏览器上时,就会往$watch队列里插入一条$watch。想象一下$watch就是那个可以检测它监视的model里时候有变化的东西。例如你有如下的代码

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

这里有个$scope.user,它被绑定在了第一个输入框上,还有个$scope.pass,它被绑定在了第二个输入框上;然后在$watch list里面加入两个$watch:

创建一个 controllers.js 文件,代码如下:

app.controller(&#39;MainCtrl&#39;, function($scope) {
 $scope.foo = "Foo";
 $scope.world = "World";
});

对应的html 文件, index.html 代码如下:

Hello, {{ World }}

这里,即便在$scope上添加了两个东西,但是只有一个绑定在了UI上,因此只生成了一个$watch. 再看下面的例子:

controllers.js

app.controller(&#39;MainCtrl&#39;, function($scope) {
 $scope.people = [...];
});

对应的html文件 index.html

<ul>
 <li ng-repeat="person in people">
   {{person.name}} - {{person.age}}
 </li>
</ul>

这样看来,又生成了多个$watch。每个person有两个(一个name,一个age),然后ng-repeat是一个循环,因此10个person一共是(2 * 10) +1,也就是说有21个$watch。 因此,每一个绑定到了浏览器上的数据都会生成一个$watch。对,那这写$watch是什么时候生成的呢? 先回顾下AngularJS的加载原理

AngularJS的加载原理:

AngularJS的模板加载分为编译(compile)和链接(linking)两个阶段,在linking阶段,AngularJS解释器会寻找每个directive,然后生成每个需要的$watch。对了,$watch就是在这个阶段生成的。

接下来,开始用到 $digest了

$digest 循环

从字面上看,digest是 “消化”的意思,总感觉这个名字怪怪的,跟不可思议的是 dirty-checking, 字面意思“脏检查”,还是不翻译为好。原作者的本意肯定不是这个意思,只可意会不可言传!

$digest 是一个循环,它在循环做什么呢? $digest 在遍历我们的$watch。 $digest 一个个地询问$watch —— “嗨,你观察的数据发生变化了没?”

这个遍历就是所谓的dirty-checking。既然所有的$watch都检查完了,那就要问了:有没有$watch更新过?如果有至少一个更新过,这个循环就会再次触发,直到所有的$watch都没有变化。这样就能够保证每个model都已经不会再变化。记住如果循环超过10次的话,它将会抛出一个异常,以免出现无限循环。 当$digest循环结束时,DOM相应地变化。

看段代码,例如: controllers.js

app.controller(&#39;MainCtrl&#39;, function() {
 $scope.name = "Foo";
 $scope.changeFoo = function() {
   $scope.name = "Bar";
 }
});

对应的html文件,index.html

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

这里只有一个$watch,因为ng-click不生成$watch(函数是不会变的)。

$digest 执行的流程是:

  1. 在浏览器按下按钮;

  2. 浏览器接收到一个事件,进入angular context。

  3. $digest循环开始执行,查询每个$watch是否变化。

  4. 由于监视$scope.name的$watch报告了变化,它会强制再执行一次$digest循环。

  5. 新的$digest循环没有检测到变化,此时浏览器拿回控制权,更新与$scope.name新值相应部分的DOM。

从中可以看出AngularJS的一个明显的不足:每一个进入angular context的事件都会执行一个$digest循环,哪怕仅仅是输入一个字母,$digest 都会遍历整个页面的所有$watch。

$apply 的应用

Angular context 是整个Angular的上下文,也可以把它理解为Angular容器,那么,是谁来决定哪些事件可以进入 Angular Context,哪些事件又不能进入呢? 其控制器在 $apply手上。

如果当事件触发时,调用$apply,它会进入angular context,如果没有调用就不会进入。你可能会问:刚才的例子并没有调用$apply,这是怎么回事呢?原来,是Angular背后替你做了。当点击带有ng-click的元素时,事件就会被封装到一个$apply调用中。如果有一个ng-model="foo"的输入框,当输入一个字母 f 时,事件就会这样调用,$apply("foo = 'f';")。

$apply的应用场景

$apply是$scope的一个函数,调用它会强制一次$digest循环。如果当前正在执行$apply循环,则会抛出一个异常。

如果浏览器上数据没有及时刷新,可以通过调用$scope.$apply() 方法,强行刷新一遍。

通过 $watch 监控自己的$scope

<!DOCTYPE html>
<html ng-app="demoApp">
<head>
 <title>test</title>
 <!-- Vendor libraries -->
  <script src="lib/jquery-v1.11.1.js"></script>
  <script src="lib/angular-v1.2.22.js"></script>
  <script src="lib/angular-route-v1.2.22.js"></script>
</head>
<body> 
 <p ng-controller="MainCtrl" >
  <input ng-model="name" />
  Name updated: {{updated}} times.
 </p> 
 <script >
  var demoApp = angular.module(&#39;demoApp&#39;,[]); 
  demoApp.controller(&#39;MainCtrl&#39;, function($scope) {
  $scope.name = "Angular";
  $scope.updated = -1;
  $scope.$watch(&#39;name&#39;, function() {
  $scope.updated++;
 });
});
 </script>
 </body>
</html>

代码说明:

当controller 执行到 $watch时,它会立即调用一次,所以把updated的值设为 -1 。 上输入框中输入字符发生变化时,你会看到 updated 的值随之变化,而且能显示变化的次数。

$watch 检测到的数据变化

小结

我们对 AngularJS的双向数据绑定有了一个初步的认识,对于AngularJS来说,表面上看操作DOM很简单,其实背后有 $watch、$digest 、 $apply 三者在默默地起着作用。这个遍历检查数据是否发生变化的过程,称之为:dirty-checking。 当你了解了这个过程后,你会对它嗤之以鼻,感觉这种方法好low 哦。 确实,如果一个DOM中有 2000- 3000个 watch,页面的渲染速度将会大打折扣。

这个渲染的性能问题怎么解决呢?随着ECMAScript6的到来,Angular 2 通过Object.observe 极大地改善$digest循环的速度。或许,这就是为什么 Angular 团队迫不及待地推出 Angular 2 的原因吧。

上面是我整理给大家的,希望今后会对大家有帮助。

相关文章:

在vue-cli中如何配置babel配置文件

使用node.js实现抖音自动抢红包功能

使用webpack打包处理bundle.js文件过大的问题

Atas ialah kandungan terperinci AngularJS双向数据绑定原理(详细教程). Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Jenis data JavaScript: Adakah terdapat perbezaan antara penyemak imbas dan nodej?Jenis data JavaScript: Adakah terdapat perbezaan antara penyemak imbas dan nodej?May 14, 2025 am 12:15 AM

Jenis data teras JavaScript adalah konsisten dalam penyemak imbas dan node.js, tetapi ditangani secara berbeza dari jenis tambahan. 1) Objek global adalah tetingkap dalam penyemak imbas dan global di Node.js. 2) Objek penampan unik Node.js, digunakan untuk memproses data binari. 3) Terdapat juga perbezaan prestasi dan pemprosesan masa, dan kod perlu diselaraskan mengikut persekitaran.

Komen JavaScript: Panduan untuk menggunakan // dan / * * /Komen JavaScript: Panduan untuk menggunakan // dan / * * /May 13, 2025 pm 03:49 PM

JavaScriptusestWotypesofcomments: Single-line (//) danMulti-line (//)

Python vs JavaScript: Analisis Perbandingan untuk PemajuPython vs JavaScript: Analisis Perbandingan untuk PemajuMay 09, 2025 am 12:22 AM

Perbezaan utama antara Python dan JavaScript ialah sistem jenis dan senario aplikasi. 1. Python menggunakan jenis dinamik, sesuai untuk pengkomputeran saintifik dan analisis data. 2. JavaScript mengamalkan jenis yang lemah dan digunakan secara meluas dalam pembangunan depan dan stack penuh. Kedua -duanya mempunyai kelebihan mereka sendiri dalam pengaturcaraan dan pengoptimuman prestasi yang tidak segerak, dan harus diputuskan mengikut keperluan projek ketika memilih.

Python vs JavaScript: Memilih alat yang sesuai untuk pekerjaanPython vs JavaScript: Memilih alat yang sesuai untuk pekerjaanMay 08, 2025 am 12:10 AM

Sama ada untuk memilih Python atau JavaScript bergantung kepada jenis projek: 1) Pilih Python untuk Sains Data dan Tugas Automasi; 2) Pilih JavaScript untuk pembangunan front-end dan penuh. Python disukai untuk perpustakaannya yang kuat dalam pemprosesan data dan automasi, sementara JavaScript sangat diperlukan untuk kelebihannya dalam interaksi web dan pembangunan stack penuh.

Python dan javascript: memahami kekuatan masing -masingPython dan javascript: memahami kekuatan masing -masingMay 06, 2025 am 12:15 AM

Python dan JavaScript masing -masing mempunyai kelebihan mereka sendiri, dan pilihan bergantung kepada keperluan projek dan keutamaan peribadi. 1. Python mudah dipelajari, dengan sintaks ringkas, sesuai untuk sains data dan pembangunan back-end, tetapi mempunyai kelajuan pelaksanaan yang perlahan. 2. JavaScript berada di mana-mana dalam pembangunan front-end dan mempunyai keupayaan pengaturcaraan tak segerak yang kuat. Node.js menjadikannya sesuai untuk pembangunan penuh, tetapi sintaks mungkin rumit dan rawan kesilapan.

Inti JavaScript: Adakah ia dibina di atas C atau C?Inti JavaScript: Adakah ia dibina di atas C atau C?May 05, 2025 am 12:07 AM

Javascriptisnotbuiltoncorc; it'saninterpretedlanguagethatrunsonenginesoftenwritteninc .1) javascriptwasdesignedasalightweight, interpratedlanguageforwebbrowsers.2)

Aplikasi JavaScript: Dari Front-End ke Back-EndAplikasi JavaScript: Dari Front-End ke Back-EndMay 04, 2025 am 12:12 AM

JavaScript boleh digunakan untuk pembangunan front-end dan back-end. Bahagian depan meningkatkan pengalaman pengguna melalui operasi DOM, dan back-end mengendalikan tugas pelayan melalui Node.js. 1. Contoh front-end: Tukar kandungan teks laman web. 2. Contoh backend: Buat pelayan Node.js.

Python vs JavaScript: Bahasa mana yang harus anda pelajari?Python vs JavaScript: Bahasa mana yang harus anda pelajari?May 03, 2025 am 12:10 AM

Memilih Python atau JavaScript harus berdasarkan perkembangan kerjaya, keluk pembelajaran dan ekosistem: 1) Pembangunan Kerjaya: Python sesuai untuk sains data dan pembangunan back-end, sementara JavaScript sesuai untuk pembangunan depan dan penuh. 2) Kurva Pembelajaran: Sintaks Python adalah ringkas dan sesuai untuk pemula; Sintaks JavaScript adalah fleksibel. 3) Ekosistem: Python mempunyai perpustakaan pengkomputeran saintifik yang kaya, dan JavaScript mempunyai rangka kerja front-end yang kuat.

See all articles

Alat AI Hot

Undresser.AI Undress

Undresser.AI Undress

Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover

AI Clothes Remover

Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool

Undress AI Tool

Gambar buka pakaian secara percuma

Clothoff.io

Clothoff.io

Penyingkiran pakaian AI

Video Face Swap

Video Face Swap

Tukar muka dalam mana-mana video dengan mudah menggunakan alat tukar muka AI percuma kami!

Artikel Panas

Nordhold: Sistem Fusion, dijelaskan
4 minggu yang laluBy尊渡假赌尊渡假赌尊渡假赌
Mandragora: Whispers of the Witch Tree - Cara Membuka Kunci Cangkuk Bergelut
3 minggu yang laluBy尊渡假赌尊渡假赌尊渡假赌

Alat panas

DVWA

DVWA

Damn Vulnerable Web App (DVWA) ialah aplikasi web PHP/MySQL yang sangat terdedah. Matlamat utamanya adalah untuk menjadi bantuan bagi profesional keselamatan untuk menguji kemahiran dan alatan mereka dalam persekitaran undang-undang, untuk membantu pembangun web lebih memahami proses mengamankan aplikasi web, dan untuk membantu guru/pelajar mengajar/belajar dalam persekitaran bilik darjah Aplikasi web keselamatan. Matlamat DVWA adalah untuk mempraktikkan beberapa kelemahan web yang paling biasa melalui antara muka yang mudah dan mudah, dengan pelbagai tahap kesukaran. Sila ambil perhatian bahawa perisian ini

mPDF

mPDF

mPDF ialah perpustakaan PHP yang boleh menjana fail PDF daripada HTML yang dikodkan UTF-8. Pengarang asal, Ian Back, menulis mPDF untuk mengeluarkan fail PDF "dengan cepat" dari tapak webnya dan mengendalikan bahasa yang berbeza. Ia lebih perlahan dan menghasilkan fail yang lebih besar apabila menggunakan fon Unicode daripada skrip asal seperti HTML2FPDF, tetapi menyokong gaya CSS dsb. dan mempunyai banyak peningkatan. Menyokong hampir semua bahasa, termasuk RTL (Arab dan Ibrani) dan CJK (Cina, Jepun dan Korea). Menyokong elemen peringkat blok bersarang (seperti P, DIV),

Muat turun versi mac editor Atom

Muat turun versi mac editor Atom

Editor sumber terbuka yang paling popular

MantisBT

MantisBT

Mantis ialah alat pengesan kecacatan berasaskan web yang mudah digunakan yang direka untuk membantu dalam pengesanan kecacatan produk. Ia memerlukan PHP, MySQL dan pelayan web. Lihat perkhidmatan demo dan pengehosan kami.

ZendStudio 13.5.1 Mac

ZendStudio 13.5.1 Mac

Persekitaran pembangunan bersepadu PHP yang berkuasa