[译]AngularJS $apply, $digest, 和$evalAsync的比较
原文:The differences between AngularJS $apply, $digest, and $evalAsync
你是不是也常在想AngularJS $apply, $digest, 和$evalAsync到底有什么差别?这个篇博客中我们将探讨一下这三个方法。
AngularJS之所以这么受欢迎,是因为它有很多的处理程序帮我们完成了绝大部分的求值运算。AngularJS让前端开发工作变的简单高效,通过指令我们可以创建html标签,还可以创建独立的模块,AngularJS确实是创建SAP的最好框架之一。
AngularJS的核心之一就是$digset循环,这是AngularJS检测和重新呈现model和view的变化的方法。在每一个$digset循环中,检测列表中的所有的检测对象都会被执行,重新计算绑定到视图的模型对象,然后又将重新渲染的视图呈现给用户。这个过程是影响AngularJS性能的主要部分。
但是很多时候,我们需要在AngularJS的上下文之外对模型进行操作,而这样的操作AngularJS是无法检测到的,也就是说它不能更新model并重新呈现视图。我们有三个方法能个完成这个工作$apply,$digset和$evalAsync,但是在我们不知其所以然的直接调用他们之前,我们需要了解一下为了解决问题我们到底需要影响多少个检测对象,影响多少层scope。
这里有多种方法可以让AngularJS执行计算,也就是让AngularJS开启一个新的$digset循环:
- $apply()
- $timeout()
- $digest()
- $evalAsync()
$apply()
$apply()会触发整个应用中的所有scope上的$digset循环。意思就是,每次我们调用$apply()都会在整个应用的生命周期中开启一个新的$digset循环。整个生命周期涉及3个主要任务:
Scope’s $apply() method transitions through the following stages:
- The expression is executed using the $eval() method.
- Any exceptions from the execution of the expression are forwarded to the $exceptionHandler service.
- The watch listeners are fired immediately after the expression was executed using the $digest() method.
调用$apply()会直接导致2个严重的问题:
- 当我们的应用中有大量的绑定的时候,过多的调用$apply()会导致严重的性能问题
- AngularJS只维护一个$digset循环,当一个$digset循环正在执行的时候,$apply()是无法立即执行的,因为它会开启一个新的$digset循环
所以在调用$apply()前,请三思而行,我们是否真的需要用$apply()。
$timeout()
在AngularJS 1.2.x之前,$timeout()是解决AngularJS上下文之外修改model问题的最简单最快速的办法,$timeout()的特别之处是AngularJS从来不会中断和阻止它完成执行。默认情况下$timeout()就是个常规的javascript setTimeout方法,当时在执行的最后会调用$apply()。 你可以通过配置让$timeout()在最后不执行$apply()。
$evalAsync()
$evalAsync()是AngularJS 1.2.x开始引入的,对我来说$evalAsync()就是$timeout的一个更聪明的兄弟。在$evalAsync()引入之前,AngularJS官方给出的在AngularJS上下文之外触发$digset的方法就是$timeout。越来越多的用户都遇到这样类似的问题,因此AngularJS在新的版本中引入了$evalAsync()。$evalAsync()的表达式会在当前$digset循环中执行而不是下一个循环中。
$evalAsync() – Executes the expression on the current scope at a later point in time.
The $evalAsync makes no guarantees as to when the expression will be executed, only that:
** it will execute after the function that has scheduled the evaluation (preferably before the DOM rendering).
** at least one $digest cycle will be performed after expression execution.
如果我们不想触发整个应用的$digset循环呢?
因为这个原因,我们有了$digset()方法。
$digset()
$digset()就是前面说到的那个循环,它会为每一个scope执行监测对象的重新计算。不同于$apply()的在$rootScope和所有的后代scope上执行监测对象计算,$digset()从它所在的scope开始执行,然后是它所有的后代scope上执行。这一巨大差别的直接表现就是,$digset()能够大大减少需要重新计算的监测对象的数量。同时有一点你需要特别注意,就是当前所在的scope的上层的scope不会更新,在view上的表现就是绑定当前scope的值更新了,但是绑定上层scope值的地方却没有更新。
总结
调用$scope.$apply()会在整个应用上开启新的$digset循环,所用活动的scope上的监测对象都被重新计算,简而言之,它会贯穿你的应用的所有的scope和绑定,看看有没有什么改动。使用$scope.$digest()而不是$scope.$apply(),将能为AngularJS减少负担,她能确切的知道从哪个scope开始、需要包含哪些子代scope。但是你时时刻刻需要记住一点,那就是它不会更新父scope,和父scope绑定相关的属性不会更新。
翻译的收获
以前看到英文文章也有翻译的想法,但是觉得没什么意义,看得懂就可以了,翻译只是简单的语言文字转换,对知识的学习理解帮助不大。今天尝试翻译了这篇文章,收获还是挺大的,首先,你得真正理解了才能用自己的话转述出来;其次,翻译的过程其实也可以算是自己总结的过程,加深了理解和牢固性;最后,学了英文还能装个逼。
翻译的不妥的地方欢迎大家热心指出
[译]AngularJS $apply, $digest, 和$evalAsync的比较的更多相关文章
- AngularJs应用
引用angularjs文件 AngularJS 应用组成如下:View(视图), 即 HTML.Model(模型), 当前视图中可用的数据.Controller(控制器), 即 JavaScript ...
- 构建自己的AngularJS - 作用域和Digest(三)
作用域 第一章 作用域和Digest(三) $eval - 在当前作用域的上下文中运行代码 Angular有多种方式让你在当前作用域的上下文中运行代码.最简单的是$eval.传入一个函数当做其參数.然 ...
- AngularJS中的digest循环$apply
欢迎大家指导与讨论 : ) 前言 Angular会拓展这个标准的浏览器流程,创建一个Angular上下文.这个Angular上下文指的是运行在Angular事件循环内的特定代码,该Angular事件循 ...
- $watch、$digest、$apply
$watch.$digest.$apply $watch 代表的就是对数据源的监听,当数据源发生变化,就会触发第二个参数的回调函数 $digest 代表触发一个数据源变化的事件 $apply 代表对于 ...
- angularJS $watch $digest $apply
一 简介AngularJS提供了一个非常酷的特性叫做双向数据绑定(Two-way Data Binding),这个特性大大简化了我们的代码编写方式.数据绑定意味着当View中有任何数据发生了变化,那么 ...
- angular的$watch,$digest和$apply
第一部分:$watch $watch是一个scope函数,用于监听模型变化,当你的模型部分发生变化时它会通知你. $watch(watchExpression, listener, objectEqu ...
- [译]ngclass expressions in angularjs
原文: http://blog.xebia.com/2014/01/31/ngclass-expressions-in-angularjs/ ngClass 指令允许你通过databinding一个表 ...
- ( 译、持续更新 ) JavaScript 上分小技巧(一)
感谢好友破狼提供的这篇好文章,也感谢写这些知识点的作者们和将他们整理到一起的作者.这是github上的一篇文章,在这里本兽也就只做翻译,由于本兽英语水平和编程能力都不咋地,如有不好的地方也请多理解体谅 ...
- Client-Side Template Injection with AngularJS
<html> <head> <meta charset="utf-8"> <script src="https://cdn.bo ...
随机推荐
- Unity 依赖注入之二
1. 构造子注入 1.1 构造子注入初级代码 container.RegisterType<IMyWork, MyWork>(new InjectionConstructor(new Bo ...
- Navicat备份远程Oracle数据库到本地
公司的数据库是本地的,我只能在公司连,回家就不能跑项目了,一跑就报SQLException,所以希望可以把数据库复制到我的本地来. 因为一直在用Navicat操作数据库,这里就分享一下用Navicat ...
- iOS 面试题搜集
1.#import和#include的区别,@class代表什么? 2.浅拷贝和深拷贝区别是什么? 3.Objective-C中类别和类扩展的区别? 4.Objective-C堆和栈的区别? 5.内存 ...
- 朴素贝叶斯算法下的情感分析——C#编程实现
这篇文章做了什么 朴素贝叶斯算法是机器学习中非常重要的分类算法,用途十分广泛,如垃圾邮件处理等.而情感分析(Sentiment Analysis)是自然语言处理(Natural Language Pr ...
- DB Scan算法的分析与实现
摘自:http://www.cnblogs.com/weixliu/archive/2012/12/08/2808815.html 根据上面第二个数据集的簇的形状比较怪异,分簇结果应该是连起来的属于一 ...
- CODEVS1090 加分二叉树
codevs1090 加分二叉树 2003年NOIP全国联赛提高组 题目描述 Description 设一个n个节点的二叉树tree的中序遍历为(l,2,3,…,n),其中数字1,2,3,…,n为节点 ...
- 51Nod 1010 只包含因子2 3 5的数 Label:None
K的因子中只包含2 3 5.满足条件的前10个数是:2,3,4,5,6,8,9,10,12,15. 所有这样的K组成了一个序列S,现在给出一个数n,求S中 >= 给定数的最小的数. 例如:n = ...
- html5地理位置定位功能小析
Geolocationd 基本原理1.GPS GPS基本原理是测量出已知位置的卫星到用户接收机之间的距离,然后综合多颗卫星的数据就可知道接收机的具体位置.适用于具备GPS功能的设备(1)优点:在 ...
- Python之路【第四篇】python基础 之基本数据类型之集合
基本数据类型之集合 set set集合,是一个无序且不重复的元素集合 # set 不允许重复的集合 set允许重复的列表但是集合是无序的 #例如 # s = {1,23,23,4,55,55} # p ...
- bat获取所有的参数
bat默认只能获取到1-9个参数,分别用%1 %2 ... %9引用,如果传给bat的参数大于9个,就必须用shift. 工作需要,要写个bat脚本,获取所有的参数,再将所有的参数传给Java,代码如 ...