angularjs基础—$scope.$apply的应用
来源:互联网 发布:linux下怎么看java目录 编辑:程序博客网 时间:2024/05/16 11:38
$apply() 和 $digest() 在 AngularJS 中是两个核心概念。
AngularJS 提供了一个非常酷的特性叫做双向数据绑定(Two-way Data Binding) ,这个特性大大简化了我们的代码编写方式。
数据绑定意味着当 View 中有任何数据发生了变化,那么这个变化也会自动地反馈到 scope 的数据上,也即意味着 scope 模型会自动地更新。
类似地,当 scope 模型发生变化时, view 中的数据也会更新到最新的值。
那么 AngularJS 是如何做到这一点的呢?当你写下表达式如 {{ aModel }} 时, AngularJS 在幕后会为你在 scope 模型上设置一个 watcher ,它用来在数据发生变化的时候更新 view 。
这里的 watcher 和你会在 AngularJS 中设置的 watcher 是一样的:
$scope.$watch('aModel', function(newValue, oldValue) { //update the DOM with newValue});
传入到 $watch() 中的第二个参数是一个回调函数,该函数在 aModel 的值发生变化的时候会被调用。当aModel 发生变化的时候,这个回调函数会被调用来更新 view ,,但是,还存在一个很重要的问题! AngularJS是如何知道什么时候要调用这个回调函数呢?即, AngularJS是如何知晓 aModel 发生了变化,才调用了对应的回调函数呢?它会周期性的运行一个函数来检查 scope 模型中的数据是否发生了变化吗?好吧,这就是 $digest 循环的用武之地了。
在 $digest 循环中, watchers 会被触发。当一个watcher 被触发时, AngularJS 会检测 scope 模型,如何它发生了变化那么关联到该 watcher 的回调函数就会被调用。那么,下一个问题就是$digest 循环是在什么时候以各种方式开始的?
在调用了 $scope.$digest() 后, $digest 循环就开始了。假设你在一个ng-click 指令对应的 handler 函数中更改了 scope 中的一条数据,此时 AngularJS 会自动地通过调用$digest() 来触发一轮 $digest 循环。当 $digest 循环开始后,它会触发每个 watcher 。这些watchers 会检查 scope 中的当前 model 值是否和上一次计算得到的 model 值不同。如果不同,那么对应的回调函数会被执行。调用该函数的结果,就是view 中的表达式内容 ( 译注:诸如 {{ aModel }}) 会被更新。除了 ng-click 指令,还有一些其它的built-in 指令以及服务来让你更改 models( 比如 ng-model , $timeout 等 ) 和自动触发一次 $digest 循环。
现在,假设你将 ng-click 指令关联到了一个 button 上,并传入了一个function 名到 ng-click 上。当该 button 被点击时, AngularJS 会将此 function 包装到一个 wrapping function中,然后传入到 $scope.$apply() 。因此,你的 function 会正常被执行,修改models( 如果需要的话 ) ,此时一轮 $digest 循环也会被触发,用来确保 view 也会被更新。
Note: $scope.$apply() 会自动地调用$rootScope.$digest() 。 $apply() 方法有两种形式。第一种会接受一个 function作为参数,执行该 function 并且触发一轮 $digest 循环。第二种会不接受任何参数,只是触发一轮$digest 循环。我们马上会看到为什么第一种形式更好。
什么时候手动调用 $apply() 方法?
如果 AngularJS 总是将我们的代码 wrap 到一个 function 中并传入 $apply(),以此来开始一轮 $digest 循环,那么什么时候才需要我们手动地调用 $apply() 方法呢?实际上, AngularJS 对此有着非常明确的要求,就是它只负责对发生于AngularJS 上下文环境中的变更会做出自动地响应 ( 即,在 $apply() 方法中发生的对于 models 的更改 ) 。 AngularJS 的 built-in 指令就是这样做的,所以任何的model 变更都会被反映到 view 中。但是,如果你在 AngularJS上下文之外的任何地方修改了 model ,那么你就需要通过手动调用 $apply() 来通知AngularJS 。这就像告诉 AngularJS ,你修改了一些 models,希望 AngularJS 帮你触发 watchers 来做出正确的响应。
我们到底什么时候需要去调用apply()方法呢?情况非常少,实际上几乎我们所有的代码都包在scope.apply()里面,像ng−click,controller的初始化,http的回调函数等。在这些情况下,我们不需要自己调用,实际上我们也不能自己调用,否则在apply()方法里面再调用apply()方法会抛出错误。如果我们需要在一个新的执行序列中运行代码时才真正需要用到它,而且当且仅当这个新的执行序列不是被angular JS的库的方法创建的,这个时候我们需要将代码用scope.apply()包起来。下面用一个例子解释:<!DOCTYPE html><html lang="en" ng-app="myapp"><head> <meta charset="UTF-8"> <title>$apply</title> <script src="js/angular.js"></script></head><body><div ng-controller="ServiceController">{{message}}</div><script> var app = angular.module('myapp', []); app.controller('ServiceController', function($scope) { $scope.message ="Waiting 2000ms for update"; setTimeout(function () { $scope.message ="Timeout called!"; }, 2000); });</script></body></html>
上面的代码执行后页面上会显示:Waiting 2000ms for update。显然数据的更新没有被angular JS觉察到。
接下来,我们将Javascript的代码稍作修改,用scope.apply()包起来。
<!DOCTYPE html><html lang="en" ng-app="myapp"><head> <meta charset="UTF-8"> <title>$apply</title> <script src="js/angular.js"></script></head><body><div ng-controller="ServiceController">{{message}}</div><script> var app = angular.module('myapp', []); app.controller('ServiceController', function($scope) { $scope.message ="Waiting 2000ms for update"; setTimeout(function () { $scope.$apply(function () { $scope.message ="Timeout called!"; }); }, 2000); });</script></body></html>
这次与之前不同的是,页面上先会显示:Waiting 2000ms for update,等待2秒后内容会被更改为:Timeout called! 。显然数据的更新被angular JS觉察到了。
NOTE:我们不应该这样做,而是用angular JS提供的timeout方法,这样它就会被自动用apply方法包起来了
如果你运行了上面的例子,你会看到 view 在两秒钟之后也会更新。唯一的变化是我们的代码现在被 wrapped 到了 $scope.$apply() 中,它会自动触发$rootScope.$digest() ,从而让 watchers 被触发用以更新 view 。
Note: 顺便提一下,你应该使用$timeout service 来代替 setTimeout() ,因为前者会帮你调用 $apply(),让你不需要手动地调用它。
总结:
需要记住的最重要的是 AngularJS 是否能检测到你对于 model 的修改。如果它不能检测到,那么你就需要手动地调用$apply() 。
- angularjs基础—$scope.$apply的应用
- AngularJS基础——$scope里的$apply方法和$watch方法
- angularjs基础—scope
- angularjs $scope.$apply()
- AngularJS and scope.$apply
- AngularJs $scope.$apply
- 浅析AngularJS中的$scope.$apply
- angularjs $scope.$apply 方法详解
- Angularjs $scope 里面的$apply方法 和 $watch方法
- angularJS $scope的$apply方法实现model刷新
- Angularjs $scope 里面的$apply 方法 和 $watch 方法
- AngularJS的作用域Scope基础
- angularJS-scope基础
- angularJS<五、$scope中的$apply和$digest>
- AngularJS 指令scope作用域问题,$apply
- [AngularJS面面观] 4. scope中的$apply方法 - Digest Cycle的触发者
- 《AngularJS》——scope的绑定策略
- AngularJS基础二($scope,过滤器)
- 每天一个linux命令(25):linux文件属性详解
- ZOJ3432 Find the Lost Sock 字符串异或
- Html 图像
- Leetcode88: Gray Code
- 转载,写的不错的一个关于dshow的文章
- angularjs基础—$scope.$apply的应用
- C# 调用CMD
- 基于Arm板linux嵌入式系统RS485串口读写通讯
- linux中用命令mail发送邮件
- Android 自定义控件实现ListView索引
- 如何从国内镜像获取android源代码
- C# 获取文件名及扩展名
- ASP.NET MVC 如何解决“上下文的模型已在数据库创建后发生更改”问题
- java例子3:计算阶乘