angular $apply

Javascript按轮次执行

Javascript代码是按轮次执行的,从第一行开始一直到最后一行依次执行,正常情况下中间不会被中断,在代码执行的过程中浏览器不会有任何响应。
不过任何异步回调,用户的输入操作等会新起一轮,新起的一轮会加入到事件轮询队列,直到下个CPU空闲会被执行。

怎么实现双向数据

一般来说有两种比较流行的方法:
1.使用自定义的对象,这个对象的数据的更新需要用到自定义的set方法,而不是直接赋值。
这样做的好处是,每次数据的更新我们都可以知道,接下来利用通知就可以更新DOM了。缺点是必须使用类似于
obj.set('key', 'value')来设置属性的值,而不能直接用ojb.key='value'这种赋值方式。
EmberJS和KnockoutJS用的就是这种实现方式。
2.在每次执行轮次的结束阶段,检测变量的值是否发生了变化,然后再通知DOM进行更新。
AngularJS用的就是第二种方式来实现双向数据绑定的。

angular $apply and $digest

在Angular里完成数据检测的工作是由$scope.$digest()来完成的,负责检测绑定的数据是否发生了变化。一般情况下我们不会直接用到这个函数,
而是用$scope.$apply(),实际上$apply会帮我们调用$digest,只是他在外面包装了一层而已。

$apply([exp]);
$apply() is used to execute an expression in angular from outside of the angular framework. (For example from browser DOM events, setTimeout, XHR or third party libraries). Because we are calling into the angular framework we need to perform proper scope life cycle of exception handling, executing watches.


Life cycle
Pseudo-Code of $apply()
function $apply(expr) {
  try {
    return $eval(expr);
  } catch (e) {
    $exceptionHandler(e);
  } finally {
    $root.$digest();
  }
}

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.
Angular文档,$apply接收一个表达式字串,由$eval执行,并在执行后调用$digest方法。

一般情况下我们很少会用到$apply函数,因为实际上所有的ng指令都帮我们包装了一层$apply,比如ng-click,$http。所以很少会显式去调用这个方法。
而且在这些指令里面再调用会报错,在$apply函数里再次调用$apply会导致报错。

如果现在有部分代码你需要在新的执行轮次运行,并且不是由Angular的内部库创建的,那么这种情况会需要用到$apply函数。这样在你的代码执行后,
变量发生了改变就会被Angular检测到。

比如下面这段代码:

function Ctrl($scope) {
  $scope.message = "Waiting for update";
    
    setTimeout(function () {
        $scope.message = "Timeout called!";
        // AngularJS 不会意识到$scope发生了变化
    }, 2000);
}

回调函数里改变了$scope.message的值,但这不会被Angular检测到(因为根本没有进行检查)。
所以我们需要手动调用$apply函数。


//use $apply
function testCtrl($scope) {
    $scope.message = 'hello world';

    setTimeout(function() { 
        $scope.$apply(function() {
            $scope.message = 'msg update';
        }); 
    }, 1000);
}
//ng $timeout 已经帮我们包装了$apply,所以一般情况下直接用$timeout就可以

ng $watch

每次在DOM增加一个变量就相当往ng 的$watch list 里增加一个$watch item
每次end of turn都会检查$watch list的变量有没有变化

//注册自己的$watch,并添加$digest时有变化的回调方法
$scope.$watch('name', function(value) {
    
});

如果自己写的组件上更新了变量值,但没有调用$apply,那么就不会检测到该变量的变化。
特别是某个地方用了$watch来检测某个值,然后这个值发生了改变,却没有执行变量值的检测,就会出现
变量值发生了改变但是$watch却不会被调用的情况。

这就很好地解释了为什么上次发生了这个事件: ``` $scope.setCity = function(item) { $scope.cityItem = item; $scope.blurCity(); }; //我却用$watch检测不到了 ```

转载于:https://www.cnblogs.com/hwencc/p/5813539.html

AngularJS中,$digest是一个循环机制,用于检查和更新作用域中的所有绑定。它会遍历作用域树,并检查每个作用域中的所有watcher。当检测到一个watcher的值发生变化时,$digest会触发这些watcher的回调函数,从而更新相应的视图。 $digest循环由AngularJS自动触发,不需要手动调用。当AngularJS检测到可能发生变化的事件(例如用户输入、HTTP请求的响应等)时,它会自动启动$digest循环。在这个过程中,AngularJS会检查每个作用域中的watcher,并更新视图以反映最新的模型状态。 然而,有时候我们需要在AngularJS上下文之外修改模型,并希望通知AngularJS进行更新。这时就可以使用$apply方法。$apply方法会触发$digest循环,强制AngularJS检查和更新所有作用域中的watcher。 一种常见的使用场景是在使用第三方库或原生JS代码时,需要手动调用$apply方法来通知AngularJS进行更新。在这种情况下,我们可以将修改模型的代码包裹在$apply函数中,以确保AngularJS能够正确地检测到变化并更新相应的视图。 总结起来,$digest是AngularJS自动触发的循环机制,用于检查和更新作用域中的所有绑定。而$apply是手动调用的方法,用于通知AngularJS在AngularJS上下文之外的代码中发生了模型的变化,需要进行更新。 :https://www.jb51.net/article/120399.htm :https://stackoverflow.com/questions/41285152/when-to-call-scope-apply-in-angularjs
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值