zoukankan      html  css  js  c++  java
  • 深入理解$watch ,$apply 和 $digest --- 理解数据绑定过程——续

    Angular什么时候不会自动为我们$apply呢?

    这是Angular新手共同的痛处。为什么我的jQuery不会更新我绑定的东西呢?因为jQuery没有调用$apply,事件没有进入angular context$digest循环永远没有执行。

    我们来看一个有趣的例子:

    假设我们有下面这个directive和controller

    app.js

    app.directive('clickable', function() {
    
    return {
      restrict: "E",
      scope: {
        foo: '=',
        bar: '='
      },
      template: '<ul style="<li>{{foo}}</li><li>{{bar}}</li></ul>',
      link: function(scope, element, attrs) {
        element.bind('click', function() {
          scope.foo++;
          scope.bar++;
        });
      }
    }
    
    });
    
    app.controller('MainCtrl', function($scope) {
      $scope.foo = 0;
      $scope.bar = 0;
    });

    它将foobar从controller里绑定到一个list里面,每次点击这个元素的时候,foobar都会自增1。

    那我们点击元素的时候会发生什么呢?我们能看到更新吗?答案是否定的。因为点击事件是一个没有封装到$apply里面的常见的事件,这意味着我们会失去我们的计数吗?不会

    真正的结果是:$scope确实改变了,但是没有强制$digest循环,监视foo 和bar$watch没有执行。也就是说如果我们自己执行一次$apply那么这些$watch就会看见这些变化,然后根据需要更新DOM。现在你在想那并不是你想要的,你想要的是点击蓝色区域的时候就更新点击数。很简单,执行一下$apply就可以了:

    element.bind('click', function() {
      scope.foo++;
      scope.bar++;
      scope.$apply();
    });

    $apply是我们的$scope(或者是direcvie里的link函数中的scope)的一个函数,调用它会强制一次$digest循环(除非当前正在执行循环,这种情况下会抛出一个异常,这是我们不需要在那里执行$apply的标志)。

    有用啦!但是有一种更好的使用$apply的方法:

    element.bind('click', function() {
      scope.$apply(function() {
          scope.foo++;
          scope.bar++;
      });
    })

    因此,如果你想使用一个jQuery插件,并且要执行$digest循环来更新你的DOM的话,要确保你调用了$apply

    使用$watch来监视你自己的东西

    你已经知道了我们设置的任何绑定都有一个它自己的$watch,当需要时更新DOM,但是我们如果要自定义自己的watches呢?简单

    app.js

    app.controller('MainCtrl', function($scope) {
      $scope.name = "Angular";
    
      $scope.updated = 0;
    
      $scope.$watch('name', function(newValue, oldValue) {
        if (newValue === oldValue) { return; } // AKA first run
        $scope.updated++;
      });
    });

    index.html

    <body ng-controller="MainCtrl">
      <input ng-model="name" />
      Name updated: {{updated}} times.
    </body>

    watch的第二个参数接受两个参数,新值和旧值。我们可以用他们来略过第一次的执行。通常你不需要略过第一次执行,但在这个例子里面你是需要的。

    总结

    好吧,我希望你们已经学会了在Angular中数据绑定是如何工作的。我猜想你的第一印象是dirty-checking很慢,好吧,其实是不对的。它像闪电般快。但是,是的,如果你在一个模版里有2000-3000个watch,它会开始变慢。但是我觉得如果你达到这个数量级,就可以找个用户体验专家咨询一下了!

  • 相关阅读:
    linux中编写同步文件的脚本
    SSH实现免密登录
    关于ISO 15765-2的解读
    设置Tera Term
    串口通信有极限速度
    三相永磁电机电流采样
    eclipse中F3快捷键无法跳转到定义的解决方法
    电脑和航模杂志和电子开发网站汇总
    MC9S08DZ60经典单片机
    STM32的SWD调试
  • 原文地址:https://www.cnblogs.com/bonelee/p/6100968.html
Copyright © 2011-2022 走看看