返回顶部
首页 > 资讯 > 前端开发 > JavaScript >AngularJS双向数据绑定原理之$watch、$apply和$digest怎么用
  • 872
分享到

AngularJS双向数据绑定原理之$watch、$apply和$digest怎么用

2024-04-02 19:04:59 872人浏览 八月长安
摘要

小编给大家分享一下angularjs双向数据绑定原理之$watch、$apply和$digest怎么用,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!背景AngularJS开发者都想知道双向

小编给大家分享一下angularjs双向数据绑定原理之$watch、$apply和$digest怎么用,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!

背景

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('MainCtrl', function($scope) {
 $scope.foo = "Foo";
 $scope.world = "World";
});

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

Hello, {{ World }}

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

controllers.js

app.controller('MainCtrl', 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('MainCtrl', 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> 
 <div ng-controller="MainCtrl" >
  <input ng-model="name" />
  Name updated: {{updated}} times.
 </div> 
 <script >
  var demoApp = angular.module('demoApp',[]); 
  demoApp.controller('MainCtrl', function($scope) {
  $scope.name = "Angular";
  $scope.updated = -1;
  $scope.$watch('name', function() {
  $scope.updated++;
 });
});
 </script>
 </body>
</html>

代码说明:

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

AngularJS双向数据绑定原理之$watch、$apply和$digest怎么用

$watch 检测到的数据变化

看完了这篇文章,相信你对“AngularJS双向数据绑定原理之$watch、$apply和$digest怎么用”有了一定的了解,如果想了解更多相关知识,欢迎关注编程网JavaScript频道,感谢各位的阅读!

--结束END--

本文标题: AngularJS双向数据绑定原理之$watch、$apply和$digest怎么用

本文链接: https://lsjlt.com/news/79370.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • AngularJS双向数据绑定原理之$watch、$apply和$digest怎么用
    小编给大家分享一下AngularJS双向数据绑定原理之$watch、$apply和$digest怎么用,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!背景AngularJS开发者都想知道双向...
    99+
    2024-04-02
  • 浅谈React双向数据绑定原理
    目录什么是双向数据绑定实现双向数据绑定数据影响视图视图影响数据如果已经学过Vue,并且深入了解过Vue的双向数据绑定的话,就会明白 Vue 2.0 双向数据绑定的核心其实是通过Obj...
    99+
    2024-04-02
  • vue2.x双向数据绑定原理是什么
    这篇文章主要介绍了vue2.x双向数据绑定原理是什么的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇vue2.x双向数据绑定原理是什么文章都会有所收获,下面我们一起来看看吧。前言双向数据绑定原理主要运用了发布订阅...
    99+
    2023-07-05
  • angular双向数据绑定的原理是什么
    Angular的双向数据绑定是通过使用脏检查(Dirty Checking)机制实现的。其原理如下: Angular会为每个绑定的...
    99+
    2023-10-24
    angular
  • vue2.x双向数据绑定原理解析
    目录前言一、index.html文件二、vue.js文件1.proxy代理发生了什么?2.observer监听数据3.订阅者Watcher4.订阅器Dep5.编译器Compiler三...
    99+
    2023-02-27
    vue2.x双向数据绑定 vue2.x双向绑定
  • proxy实现vue3数据双向绑定原理
    目录一、proxy对比Object.defineProperty的优点二、、proxy监听对象的简单实现1.代理对象简单实现2.补充知识 Reflect3.proxy方法三、手写vu...
    99+
    2024-04-02
  • Android数据双向绑定原理实现和应用场景
    目录一、使用databinding类二、双向绑定安卓的数据双向绑定类似Vue这种前端框架,只要修改模型的数据,页面上显示的数据也会跟着变化,不需要取出控件来赋值。 一、使用datab...
    99+
    2023-05-17
    Android数据双向绑定 Android数据绑定 Android双向绑定
  • 怎么理解JavaScript数据双向绑定
    本篇内容介绍了“怎么理解JavaScript数据双向绑定”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!模板...
    99+
    2024-04-02
  • vue中双向数据绑定的原理是什么
    本篇文章为大家展示了vue中双向数据绑定的原理是什么,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。双向绑定的思想双向数据绑定的思想就是数据层与UI层的同步,数据再两...
    99+
    2024-04-02
  • vue中数据双向绑定的原理是什么
    vue中数据双向绑定的原理是什么,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。前端的数据双向绑定指的是view(视图)和model(数据)...
    99+
    2024-04-02
  • 面试问题Vue双向数据绑定原理
    目录前言具体步骤什么是Object.defineProperty一、访问器属性二、简单的数据双向绑定实现方法三、 实现任务的思路四、DocumentFragment五、初始化数据绑定...
    99+
    2024-04-02
  • 深入了解Vue中双向数据绑定原理
    目录数据的变化反应到视图命令式操作视图声明式操作视图小结视图的变化反应到数据现存的问题数据的变化反应到视图 前面我们了解到数据劫持之后,我们可以在数据发生修改之后做任何我们想要做的事...
    99+
    2024-04-02
  • Vue双向数据绑定原理的示例分析
    小编给大家分享一下Vue双向数据绑定原理的示例分析,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!双向数据绑定的原理:采用“数据劫持”结合“发布者-订阅者”模式的方式,通过“Object.defineProperty()”方...
    99+
    2023-06-14
  • vue双向数据绑定原理分析、vue2和vue3原理的不同点
    目录Vue数据双向绑定原理(一)Vue2双向数据绑定原理(一)Vue3双向数据绑定原理受疫情影响,今年各行业不景气,各岗位的跳槽形势也不是很高。所以趁此机会好好蓄力,复习面试题吧。现...
    99+
    2022-12-08
    vue双向数据 vue数据绑定原理 vue2和vue3原理
  • Vue2.0/3.0双向数据绑定的实现原理是什么
    这篇文章给大家分享的是有关Vue2.0/3.0双向数据绑定的实现原理是什么的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。vue是什么Vue是一套用于构建用户界面的渐进式JavaScript框架,Vue与其它大型框...
    99+
    2023-06-14
  • vue 数据双向绑定怎么实现
    这篇文章给大家分享的是有关vue 数据双向绑定怎么实现的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。1. 前言实现简易版的数据双向绑定2. 代码实现2.1 目的分析本文要实现的效果如下图所示:本文用到的HTML和...
    99+
    2023-06-06
  • angular双向数据绑定怎么实现
    Angular双向数据绑定可以通过以下步骤来实现:1. 在HTML模板中使用双大括号({{}})将数据绑定到HTML元素上。例如:{...
    99+
    2023-09-21
    angular
  • MVVMLight怎么实现双向数据绑定
    这篇文章主要介绍“MVVMLight怎么实现双向数据绑定”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“MVVMLight怎么实现双向数据绑定”文章能帮助大家解决问题。第一步:先写一个Model,里面...
    99+
    2023-06-29
  • vue双向数据绑定怎么实现
    Vue的双向数据绑定是通过v-model指令来实现的。1. v-model是Vue提供的一个指令,用于在表单元素上实现双向数据绑定。...
    99+
    2023-08-09
    vue
  • Vue2.0/3.0双向数据绑定的实现原理详解
    Vue2.0/3.0 双向数据绑定的实现原理 双向数据绑定简意 即数据的改变能让页面重新渲染 Vue2.0 ES5的原理: Object.defineProperty 对数据进行拦...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作