zoukankan      html  css  js  c++  java
  • angular1.x 脏检测

    写在前面

      双向绑定是angular的大亮点,然后支撑它的就是脏检测。一直对脏检测都有一些理解,却没有比较系统的概念。

      以下是我阅读网上博文以及angular高级程序设计的理解与总结。

      接收指导与批评。

    脏检查:

      将原对象赋值一份快照。在某个时间,遍历比较这个对象和快照(新旧值),如果不一样就执行执行某些操作。

    angular中的脏检查:

      1.不会检查所有的对象。当对象被绑定到html会检查,手动$scope.$watch()的会检查。检查的手段就是为这些对象创建(watcher)对象。并push到(watcher队列) 2.不会检查所有的属性。只要被绑定的属性才会被注册。 在angular程序初始化时,会将绑定的对象的属性添加为监听对象(watcher),也就是说一个对象绑定了N个属性,就会添加N个watcher。

    angular注册watcher对象

      angualr会为每一个绑定到DOM的对象/对象的属性,创建一个watcher对象,(使用$scope.$watch()方法也会创建),watcher对象有好几个属性,(下面是笔者理解抽象出来的,并不是真的属性名

    watch = {
      name:'',      //当前的watch 对象 观测的数据名,锁定监听的是什么
      getNewValue:function($scope){ //获取监听属性的最新值
          ...
          return newValue;
          },
      listener:function(newValue,oldValue){  // 先比较新值与旧值判断是否继续执行,一般负责使用新值更新DOM页面,也可以是$watch方法注册的回调函数
          ...
      }
    }

      $$watchers的watcher属性截图

    $scope.$$watchers队列

      每一个创建好的watcher对象会被push到各自的controller作用域的$scope.$$watchers队列里面。
      脏检测就是遍历watchers的过程。


    脏检测通过两个方法触发:$digest(), $apply()
      $digest:是遍历当前作用域以及其子作用域的$$watchers队列,并执行其listener。
      $apply:是对$digest()的封装。接受一个函数参数(包含脱离angular环境的逻辑,需要却不会自己触发脏检测, 所以$apply帮他触发一下。),$apply在执行了参数函数之后自动调用 $rootScope.$digest (就是从更作用于开始遍历每一个$scope.$$watchers队列)


      如果你对自己的逻辑比较清楚,可以不使用$apply,改用$scope.$digest(),只遍历当前与其子作用域。不用从rootScope开始

      如果不是很了解逻辑,建议还是使用$apply()从rootScope开始,避免需要更新的值没有被更新,并且$apply会把参数函数放在try...catch里面,如果逻辑发生错误。会把错误传给$exceptionHandler service来处理。

    $scope.data = 0;
    $scope.data2 = 0;
    // code 1
    setInterval(function() {
      $scope.$apply(function() {
        $scope.data++;
        console.log('first:', $scope.data)
      });
    }, 2000);
    
    // code 2
    setInterval(function() {
      $scope.data2++;
      console.log('second:', $scope.data2)
      $scope.$apply();    // 对比code1,少了try...catch
      // $scope.$digest();  // 只遍历当前及其子作用域的$$watchers队列
    },2000)

    一次脏检测中$digest()执行的次数?

      在一个脏检测中,digest至少会执行两次

      因为某一个监听属性的listener可能会改变另一个监听属性的值。因此,angular需要在一次$digest()之后判断这一轮digest中时候有没有属性发生变化并执行了listener,如果有,angular必须再次调用$digest();当已经连续触发了10次$digest(),若还有属性发生变化,angular就会认为你的逻辑错了并console报告。因此在$scope.$watch时要自己多加注意理解好逻辑问题。

    什么时候会触发脏检测?

      好像不少人有一个误区。angular是定时执行脏检测的!!!!(我之前还问过,angular设置多久执行一次脏检测,无言以对)

      angular并不是定时的。会触发脏检测的有以下:

      1. controller 初始化
      2. 几乎所有ng-开头的事件(ng-click,ng-change...)
      3. http请求
      4. $timeout,$interval
      5. 手动调用$apply(), $digest()

      回头想想,如果是定时的,怎么会有脱离angualr环境的说法呢?

  • 相关阅读:
    java Activiti 工作流引擎 SSM 框架模块设计方案
    自定义表单 Flowable 工作流 Springboot vue.js 前后分离 跨域 有代码生成器
    数据库设计的十个最佳实践
    activiti 汉化 stencilset.json 文件内容
    JAVA oa 办公系统模块 设计方案
    java 考试系统 在线学习 视频直播 人脸识别 springboot框架 前后分离 PC和手机端
    集成 nacos注册中心配置使用
    “感恩节 ”怼记
    仓颉编程语言的一点期望
    关于System.out.println()与System.out.print("\n")的区别
  • 原文地址:https://www.cnblogs.com/miaowwwww/p/6261947.html
Copyright © 2011-2022 走看看