文档章节

AngularJS,为什么我们要使用$apply()?在什么时候使用?

随风所欲
 随风所欲
发布于 2015/11/24 14:28
字数 791
阅读 73
收藏 1

初学angular的时候,我们在使用中经常遇到更改scope里的值,但是model没有相应的更新。于是我们发现angular有一个$apply()方法,来update我们的model.但是我们使用过后,有时候控制台会报出错误:

Error: $digest / $apply already in progress。

然后我们百度得到的解决方案是:

if(!$scope.$$phase) { 
    //$digest or $apply 
}

一直一来,我在我初学angular后做的项目里也是这么干的。直到某一天我看到了有人说:

然后我开始反思,我的程序是是不是哪里写的有问题?在我翻看了很多大神的文章后,我大致理解了。

为什么我们会使用到$apply()?

        一般情况,我们在 controller初始化、使用$http的callbacks、类似ng-click这类的ng-*事件时,angular都会用$apply()包起来当里面的function或者一个Angular expression string执行后,就会去调用$scope.$digest()更新数据的绑定。所以是不需要你去主动调用$apply()的,且你在$apply()里面调用$apply()将会抛错的。就是如你们看到的$digest / $apply already in progress

        如果我们用到了$apply()那么应该是以下情况:

        a.  代码处于$digest loop(更新周期)外,比如在"link"指令(directive)响应函数内部使用。也就是说,只能在$controller之外调用$apply,这样它就可以访问到HTML或其他控制器的声明代码 - 比如apply调用link指令并触发相应功能,这时侯是肯定在$digest loop之外的。

        b.  在你的代码块里面还包含有新的函数块,比如:

function Ctrl($scope) {
  $scope.message = "Waiting 2000ms for update";    
    setTimeout(function () {
        $scope.message = "Timeout called!";        
        // AngularJS unaware of update to $scope
    }, 2000);
}

    message在内部匿名函数内被赋值,是无法触发angular的脏值检测的,正确的做法就是:

function Ctrl($scope) {
  $scope.message = "Waiting 2000ms for update";    
    setTimeout(function () {
        $scope.$apply(function () {
            $scope.message = "Timeout called!";
        });
    }, 2000);
}

如何正确使用$apply()?

$scope.$apply()接收一个函数或Angular表达式字符串,并执行它,然后调用 $scope.$digest()来更新所有绑定或侦听者。

但有些人的做法是像我最初一样,直接使用

if(!$scope.$$phase) { 
    //$digest or $apply
}

这个做法就会导致如果你的代码出错,然后又没有相应的处理机制那么程序就会卡死在那里。

$apply不仅仅执行你的代码,它内部的try / catch语句让你的错误总是能被捕捉到,并且$digist是最后的保障,它意为着即使一个错误抛出,它仍能运行。所以正确的做法是:

$scope.$apply(function () {
    $scope.message = "Timeout called!";
});

以上是我观点,如有错误,请指证!

参看文章:AngularJS and scope.$apply

© 著作权归作者所有

共有 人打赏支持
随风所欲
粉丝 2
博文 9
码字总数 7237
作品 0
成都
私信 提问
再谈angularJS数据绑定机制及背后原理—angularJS常见问题总结

Angular 的数据绑定采用什么机制,详述原理? 脏检查机制。阐释脏检查机制,必须先了解如下问题。 单向绑定(ng-bind) 和 双向绑定(ng-model) 的区别? ng-bind 单向数据绑定($scope ->...

634117608
2018/04/19
0
0
Angularjs的$apply及其优化使用

今天,我们要聊得是Angularjs中的小明星$apply。当我们数据更新了,但是view层却没反应时,总能听到有人说,用apply吧,然后,懵懂无知的我们,在赋值代码后面加了$scope.$apply(),然后就惊喜...

北辰狼月
2018/07/01
0
0
angularjs双向绑定后,发生了什么事情?是什么可以让view层和controller层进行绑定的?

大家好,我是IT修真院北京总院第24期的学员,一枚正直纯洁善良的web程序员 今天给大家分享一下,修真院官网js任务7,深度思考中的知识点——angularjs双向绑定后,发生了什么事情?是什么可以...

我是一只北极熊啊
2017/10/16
0
0
使用 AngularJS 实现 WebBinding

下载 demo - 2.8 MB 下载源代码 - 39.8 KB 介绍 在之前的文章 (WebBinding - 如何将客户端JavaScript对象绑定到服务器端的 .NET 对象)中, 我们实现了一个将.Net服务器端对象绑定到JavaScrip...

oschina
2015/02/27
1K
0
【前端】—聊聊我认识的Angular

前言 最近接触的项目前端用到了Angular框架,之前略有耳闻,从vue换到Angular,感觉东西差不多,还是要系统学习的,先来了解下。 正文 1、Angular 的发展 AngularJS 是一款来自Google的前端J...

zt15732625878
2018/05/19
0
0

没有更多内容

加载失败,请刷新页面

加载更多

SpringCloud 与 SpringBoot 的版本兼容

Spring Cloud Finchley 构建并使用 Spring Boot 2.0.x,预计不会与Spring Boot 1.5.x一起使用Spring Cloud Edgware Spring Boot 1.5.xDalston 和 Edgware 发布版基于Spring Boot 1......

晨猫
18分钟前
2
0
microtime 记录的时间点,以毫秒来显示,并显示每一阶段占用百分比。统计代码执行时间。

function mini_bench_to($arg_t, $arg_ra=false){ $tttime=round((end($arg_t)-$arg_t['start'])*1000,4); if ($arg_ra) $ar_aff['total_time']=$tttime; else $aff="total......

lwkai
19分钟前
4
0
Docker 解决容器时间与主机时间不一致的问题三种解决方案

这篇文章主要介绍了Docker 解决容器时间与主机时间不一致的问题的相关资料,这里提供了三种方法,供大家参考,需要的朋友可以参考下 Docker容器时间与主机时间不一致 通过date命令查看时间 查...

Jack088
21分钟前
5
0
neo4j 开启远程web访问7474端口 以 用浏览器打开远程neo4j的web控制台界面

一、对于3.0以前的版本 在安装目录的 $NEO4J_HOME/conf/neo4j.conf 文件内,找到下面一行,将注释#号去掉就可以了 #dbms.connector.https.address=localhost:7474 改为 dbms.connector.https...

Airship
21分钟前
2
0
集合排序

根据指定规则,对集合元素进行自定义排序 List<Map<String, Object>> list= data.stream().sorted(new Comparator<Map>() { @Override public int compare(Map o1, Map o2) { Comparator c =......

zhaochaochao
23分钟前
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部