加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

angularJs $apply

发布时间:2020-12-17 10:32:19 所属栏目:安全 来源:网络整理
导读:Scope的特性 接下来,看看Scope有哪些特性呢? Scope提供$watch方法监视Model的变化。 Scope提供$apply方法传播Model的变化。 Scope可以继承,用来隔离不同的application components和属性访问权限。 Scope为Expressions的计算提供上下文。 对于这四点特性,
  • Scope的特性

  接下来,看看Scope有哪些特性呢?

  1. Scope提供$watch方法监视Model的变化。
  2. Scope提供$apply方法传播Model的变化。
  3. Scope可以继承,用来隔离不同的application components和属性访问权限。
  4. Scope为Expressions的计算提供上下文。

对于这四点特性,因为我之前学习过ActionScript、C++、Java,所以第一、三、四点不难理解,唯独第二点感觉有点云里雾里。本着打破沙锅问到底的原则,我还是通过Google搜到了一些东西。对于有经验的老手,板砖请轻拍!

  • 源起Javascript

首先,乍一看, scope. scope.apply()似乎就是一个使得bindings得到更新的普普通通的方法。但稍微多想一点,为什么我们需要它?一般在什么时候用它呢?用弄明白这两个问题,还得从Javascript说起。在Javascript代码里,都是按照一定顺序来执行的,当轮到一个代码片段执行的时候,浏览器就只会去执行当前的片段,不会做任何其他的事情。所以有时候一些做得不是很好的网页,当点击了某个东西之后会卡住,Javascript的工作方式就是会导致这一现象原因之一!下面我们有一段代码来感受一下:

var button = document.getElementById('clickMe');
function buttonClicked () { alert('the button was clicked'); }
button.addEventListener(
'click',buttonClicked);
function timerComplete () { alert('timer complete'); }
setTimeout(timerComplete,
5000);

当加载Javascript代码时,先先找一个一个id叫“clickMe”的按钮,然后添加一个监听器,然后设置超时。等待5秒,会弹出一个对话框。如果刷新页面并立即点击clickMe按钮,会弹出一个对话框,如果你不点击OK,timerComplete函数永远没有机会执行。

  • 如何更新bindings
  • 好了,扯了一些看似不相关的东西之后,我们回归正题。angular JS是怎么知道什么时候数据的变化和页面需要更新的呢?代码需要知道什么时候数据被修改了,但是现在又没有一种方法直接去通知说某个对象上的数据变了(尽管ECMAScript 5正在尝试解决这一问题,但也还是处于实验阶段)。而目前比较主流的策略有以下有两种解决方案。一种是需要用特殊的对象,让所有的数据都只能通过调用对象的方法设置,而不是直接通过property指定。这样的话,所有的修改就可以被记录下来了,就知道什么时候页面需要更新了。这样做的弊端就是我们必须去继承一个特殊的对象。对于赋值也只能通过object.set('key','value')而不是object.key=value的方式。在框架中,像EmberJS和KnockoutJS就是这么干的(虽然我都没接触过——囧)。另一种就是angular JS采用的方式,在每一次Javascript代码执行序列执行结束后都去检查是否有数据的改变。这看起来似乎并不高效,甚至严重影响性能。但是angular JS采用了一些比较巧妙的手段解决了这个问题(还没研究过,目前尚不明确)。这么做的好处就是,我们可以随便使用任意对象,对于赋值方式也没有限制,而且对于数据的改变也能觉察到。
    对于angular JS采取的这种解决方案,我们关心的是什么时候数据发生了变化,而这也正是 scope. scope.apply()派上用场的地方。对于检查绑定的数据到底有没有发生变化,实际上是由 scope. scope.digest()完成的,但是我们几乎从来就没有直接调用过这个方法,而是调用 scope. scope.apply()方法,是因为在 scope. scope.apply()方法里面,它会去调用 scope. scope.digest()方法。 scope. scope.apply()方法带一个函数或者一个表达式,然后执行它,最后调用 scope. scope.digest()方法去更新bindings或者watchers。

  • 什么时候用$apply()
  • 还是那个问题,那我们到底什么时候需要去调用 apply() apply()方法呢?情况非常少,实际上几乎我们所有的代码都包在scope. apply()ng?clickcontroller apply()里面,像ng?click,controller的初始化,http的回调函数等。在这些情况下,我们不需要自己调用,实际上我们也不能自己调用,否则在 apply() apply()方法里面再调用apply()方法会抛出错误。如果我们需要在一个新的执行序列中运行代码时才真正需要用到它,而且当且仅当这个新的执行序列不是被angular JS的库的方法创建的,这个时候我们需要将代码用 scope. scope.apply()包起来。下面用一个例子解释:
    [HTML]

    <div ng:app ng-controller="Ctrl">{{message}}</div>

    [Javascript]

    functionCtrl($scope) {
      $scope.message ="Waiting 2000ms for update";    
      setTimeout(function () {
        $scope.message ="Timeout called!";
         // AngularJS unaware of update to $scope
      },2000); 
    }
    上面的代码执行后页面上会显示:Waiting 2000ms for update。显然数据的更新没有被angular JS觉察到。
    接下来,我们将Javascript的代码稍作修改,用 scope. scope.apply()包起来。
    [Javascript]

    functionCtrl($scope) {
      $scope.message ="Waiting 2000ms for update"; 
      setTimeout(function () {
        $scope.$apply(function () {
           $scope.message ="Timeout called!";
          });
      },2000); 
    }
    这次与之前不同的是,页面上先会显示:Waiting 2000ms for update,等待2秒后内容会被更改为:Timeout called!。显然数据的更新被angular JS觉察到了。
    NOTE:我们不应该这样做,而是用angular JS提供的 timeout timeout方法,这样它就会被自动用apply方法包起来了。

  • 科学是把双刃剑
  • 最后,我们再来瞅一眼 scope. scope.apply()和 scope. scope.apply(function)方法吧!虽然angular JS为我们做了很多事情,但是我们也因此丢失了一些机会。从下面的伪代码一看便知:

    function$apply(expr) {   try {     return$eval(expr);   } catch(e) {     $exceptionHandler(e);   } finally {     $root.$digest();   } }
      它会捕获所有的异常并且不会再抛出来,最后都会调用$digest()方法。

  • 总结一下
  •   $apply()方法可以在angular框架之外执行angular JS的表达式,例如:DOM事件、setTimeout、XHR或其他第三方的库。

    (编辑:李大同)

    【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

      推荐文章
        热点阅读