• 深入理解$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,它会开始变慢。但是我觉得如果你达到这个数量级,就可以找个用户体验专家咨询一下了!

  • 相关阅读:
    结对第一次—疫情统计可视化(原型设计)
    软工实践寒假作业(2/2)
    test
    软工实践寒假作业(1/2)
    json的基本用法
    个人作业——软件工程实践总结&个人技术博客
    个人作业——软件评测
    结对第二次作业——某次疫情统计可视化的实现
    寒假作业(2/2)— 疫情统计
    软工实践寒假作业(1/2)
  • 原文地址:https://www.cnblogs.com/bonelee/p/6100968.html
Copyright © 2020-2023  润新知