Angularjs的$apply及其优化使用
今天,我们要聊得是Angularjs中的小明星$apply。当我们数据更新了,但是view层却没反应时,总能听到有人说,用apply吧,然后,懵懂无知的我们,在赋值代码后面加了$scope.$apply(),然后就惊喜的发现。噢,真的更新了。
然而,有些时候,编译器会无情的给你返回
Error: $digest already in progress
那么,导致这些现象的原因时什么的呢?$apply究竟干了啥?听我慢慢道来。
一.$apply的作用
$apply()函数可以从Angular框架的外部让表达式在Angular上下文内部执行。
上面是AngularJs权威教程中的一句话。什么意思呢?
首先,你要清楚,在原生js或者第三方框架下,修改model,是有可能不会触发视图更新的,比如setTimeout、jquery插件。为什么?因为他们脱离了Angularjs的上下文,Angularjs并不能监听到数据的改变。看例子。
1.setTimeout
html:
<p>{{name}}</p>
js:
$scope.name="张三";
setTimeout(function(){
$scope.name = '李四';
//$scope.$apply()
},500)
首先,name等于张三,500ms后,我把他赋值为李四,但是,页面上并没有改变,依然是张三。
而,我们把$scope.$apply()放开,就正常了,张三成功变为李四。
2.第三方插件
html:
<p>Date: <input type="text" id="datepicker"></p>
<p>
<header>所选日期</header>
{{selectedDate}}
</p>
js:
$scope.selectedDate = '';
$( function() {
$( "#datepicker" ).datepicker({
onClose: function( selectedDate ) {
$scope.selectedDate = selectedDate;
// $scope.$apply();
}
});
} );
这是jquery的datepicker插件,当我们选定日期后,下面的日期应该随之显现,而现在却没有。这种情况就必须依靠$apply(),才能更新视图。
以上两种情况,都因为不处于Angularjs上下文中,导致监听不到数据的变化。而$apply究竟干了什么,才导致数据更新正常了呢?
其实$apply相当于一个触发器,它的作用就是触发digest循环,从而更新视图。
在digest是Angularjs的核心,是它实现了神奇的数据绑定。凡是触发事件,必会触发digest循环,比如,我们数值的ng事件,click啊,change,实际上都是触发了digest循环。
所以,我们所做的事,其实就是手动触发了digest循环。关于digest循环,属于题外话,这里不做过多介绍,想深入了解的同学,可以看看书籍,或者百度。
二.更好地运用digest循环
在Angularjs中,除了$apply可以触发digest循环外,还有其他的方法,也可以触发此循环。而且$apply往往时最坏的选择。下面推荐一些更好的选择。
1.$digest
$scope.$digest()的速度要比$apply要快,因为它只更新当前作用域和子作用域的值,对于父作用域时不管的。而$apply还要评估父作用域,这就大大消耗了性能。
2.$timeout
用$timeout去代替你的setTimeout,$timeout作为Angularjs的自带服务,当然时更契合Angularjs环境啦。它会隐性触发digest循环,而且它会延迟执行,会在上一个digest循环完成后的下一刻,触发digest循环,这样就不会出现上文所说的
$digest already in progress
我们把setTime的代码放到$timeout中
$timeout(function(){
$scope.name = '李四';
},500)
这就能正常工作了,看,没有讨厌的apply了!
3.$evalAsync
最推荐的应该时这个方法了。如果当前正好有一个digest循环在执行,那么它就会把导致digest循环的操作,放到当前digest循环中去执行。而$timeout是要等到当前digest循环执行完,再执行一次digest循环才可以。所以evalAsync执行更快,性能更好。我们可以像$timeout那样去调用它,即
$scope.$evalAsync(
function( $scope ) {
console.log( "$evalAsync" );
}
);
以上,就是今天要说的全部内容。Angularjs中还藏着许多奥秘,和更好的使用方法,希望大家可以深入地研究,分享出更好的文章。
下面是可执行的代码,大家可以探究探究
https://codepen.io/hanwolfxue/pen/yEZbYQ
Angularjs的$apply及其优化使用的更多相关文章
- AngularJS应用页面切换优化方案
葡萄城的一款尚在研发中的产品,对外名称暂定为X项目.其中使用了已经上市的Wijmo中SpreadJS产品,另外,在研发过程中整理了一些研发总结分享给大家.如本篇的在页面切换的过程中优化方案,欢迎大家跟 ...
- angularJS中$apply()方法详解
这篇文章主要介绍了angularJS中$apply()方法详解,需要的朋友可以参考下 对于一个在前端属于纯新手的我来说,Javascript都还是一知半解,要想直接上手angular JS,遇到的 ...
- angularjs $scope.$apply 方法详解
myApp.controller('firstController',function($scope,$interval){ $scope.date = new Date(); setInterval ...
- AngularJs应用页面切换优化方案(转)
目录[-] 前言 场景 使用resolve来提前请求数据 为页面加入切换动画 总结 葡萄城的一款尚在研发中的产品,对外名称暂定为X项目.其中使用了已经上市的wijmo中SpreadJS产品,另外,在研 ...
- angularJS之$apply()方法
这几天,根据buddy指定的任务,要分享一点angular JS的东西.对于一个在前端属于纯新手的我来说,Javascript都还是一知半解,要想直接上手angular JS,遇到的阻力还真是不少.不 ...
- angularJS $watch $apply $digest
看O'Reilly的书看到$watch这部分,不过没看懂,网上很多资料也含糊不清,不过还是找到了几个好的,简单记录一下. 一句话说明,$watch是用来监视变量的,好了直接上代码 <html&g ...
- AngularJS中$apply
$apply是$scope下的特性,传播model的变化.下面的例子两秒之后控制台会显示出已经更新的model, 然而, view 并没有更新.$digest循环不会只运行一次.在当前的一次循环结束后 ...
- 04、AngularJS的ng-bind、多个控制器和apply
这篇,讲一下angularjs的ng-bind指令,多个控制器,以及手动触发angularjs的脏检查,我直接把代码贴,顺着代码讲. <!DOCTYPE html> <html> ...
- 《AngularJS学习整理》系列分享专栏
<AngularJS学习整理>系列分享专栏 <AngularJS学习整理>已整理成PDF文档,点击可直接下载至本地查阅https://www.webfalse.com/re ...
随机推荐
- codeforces 1114C
题目连接 : https://codeforces.com/contest/1114/problem/C 题目大意:给一个整数n(1e18>=n>=0),和一个整数k(1e12>=k ...
- vbs自由选择启动bat文件
1.首先创建一个文件夹用来放bat文件和配置文件. 2.然后在bat文件中写入启动程序.中间红色框是启动程序,外面程序是用来隐藏命令提示符的. 3.txt配置文件配置vbs启动项,vbs只能找到此文件 ...
- 谭浩强 c++程序设计第一章课后习题 第10题
#include <iostream> using namespace std; int main() { int a,b,c; cout<<"请输入三个整数类型的数 ...
- C++ ADL
即在一个名称作为调用运算符的左操作数时,并且这个名字是一个无限定名称时,在无限定查找到的名字集合中额外增加的一个规则使集合范围扩大(从而可以定位到其他一些限定名称),通常是用来保证定义在不同命名空间的 ...
- 【前端_js】Chrome禁止缓存的方法
在前端开发中,浏览器缓存使得我们改了代码后页面不变,得经常手动清理缓存. 1.按如下操作即可禁用浏览器缓存, 这种方法基本能够做到完全禁止缓存,然而缺点是必须要将开发模式一直打开,占用屏幕空间.而且, ...
- Python学习——numpy.random
numpy.random.rand numpy.random模块作用是生成随机数,其中numpy.random.rand(d0, d1, ..., dn):生成一个[0,1)之间的随机浮点数或N维浮点 ...
- PKI
公钥基础设施(Public Key Infrastructure,简称PKI)是眼下网络安全建设的基础与核心,是电子商务安全实施的基本保障,因此,对PKI技术的研究和开发成为眼下信息安全领域的热点.本 ...
- mybatis中实现动态SQL
动态SQL语句,也就意味着SQL语句不在是一成不变的而是具有多样性. if if的用法还是跟平常差不多的(不过没有else if也没有else) <update id="modify& ...
- Vue 使用History记录上一页面的数据
UI Mvvm 前端数据流框架精讲 Vue数据双向绑定探究 面试问题:Vuejs如何实现双向绑定 数据双向绑定的探究和实现 需求 从列表页的第二页进入详情页,返回时列表页仍然显示在第二页: 从列表页的 ...
- 23.VUE学习之-列表的排序sort
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...